// ----------------------------------
// RSDK Project: Sonic 1/Sonic 2
// Script Description: Player Object Object
// Script Author: Christian Whitehead/Simon Thomley
// Unpacked by Rubberduckycooly's script unpacker
// ----------------------------------

// Aliases
private alias 1 		: TYPE_PLAYEROBJECT
public alias  256 		: GROUP_PLAYERS
public alias  65536 	: HITBOX_AUTO
public alias  arrayPos6 : currentPlayer
public alias  arrayPos7 : playerCount

// Draw Order
private alias -1 : DRAWORDER_PLAYER

// Players
private alias 0 : PLAYER_SONIC_ALONE
private alias 1 : PLAYER_TAILS_ALONE
private alias 2 : PLAYER_KNUX_ALONE
private alias 3 : PLAYER_SONIC_AND_TAILS

// Shields
private alias 0 : SHIELD_NONE
private alias 1 : SHIELD_NORMAL
private alias 2 : SHIELD_BUBBLE
private alias 3 : SHIELD_FIRE
private alias 4 : SHIELD_LIGHTNING

// Variables
private alias object.type			 :	player.type
private alias object.groupID		 :	player.groupID	 		// Normally GROUP_PLAYERS, unless in Debug Mode or some other strange scenario
private alias object.entityPos		 :	player.entityPos 		// Where the player is on the object list - P1 should be 0, P2 should be 1
private alias object.state			 :	player.state
private alias object.visible		 :	player.visible
private alias object.propertyValue	 :	player.character
private alias object.xpos			 :	player.xpos				// Total world-space position (0x10000 == 1.0)
private alias object.ypos			 :	player.ypos
private alias object.ixpos			 :	player.ixpos			// Screen space position (1 == 1)
private alias object.iypos			 :	player.iypos
private alias object.lookPosX		 :	player.lookPosX			// Camera offset based on this player's position
private alias object.lookPosY		 :	player.lookPosY
private alias object.xvel			 :	player.xvel				// Based on world-space (see above)
private alias object.yvel			 :	player.yvel
private alias object.speed			 :	player.speed			// Based on world-space (see above)
private alias object.rotation		 :	player.rotation			// Note: Because this is stored as a byte, it goes from 0-255, not 0-360!
private alias object.angle			 :	player.angle			// See above
private alias object.direction		 :	player.direction
private alias object.gravity		 :	player.gravity			// 1 if falling, 0 otherwise. Not to be confused with player.gravityValue, see there for more info
private alias object.frame			 :	player.frame
private alias object.animation		 :	player.animation
private alias object.prevAnimation	 :	player.prevAnimation
private alias object.animationSpeed	 :	player.animationSpeed
private alias object.animationTimer	 :	player.animationTimer
private alias object.drawOrder		 :	player.drawOrder
private alias object.pushing		 :	player.pushing
private alias object.controlLock	 :	player.controlLock
private alias object.controlMode	 :	player.controlMode
private alias object.interaction	 :	player.interaction		// Will the object interact with tiles?
private alias object.scrollTracking	 :	player.scrollTracking	// Determines if the camera will track the player's position or just follow it
private alias object.collisionMode	 :	player.collisionMode
private alias object.collisionLeft	 :	player.collisionLeft
private alias object.collisionTop	 :	player.collisionTop
private alias object.collisionRight	 :	player.collisionRight
private alias object.collisionBottom :	player.collisionBottom
private alias object.collisionPlane	 :	player.collisionPlane
private alias object.floorSensorC	 :	player.floorSensorC
private alias object.floorSensorL	 :	player.floorSensorL
private alias object.floorSensorR	 :	player.floorSensorR
private alias object.tileCollisions	 :	player.tileCollisions
private alias object.priority		 :	player.priority

// *Object-wise* input, not to be confused with inputPress.X and inputDown.X
private alias object.jumpPress	:	player.jumpPress
private alias object.jumpHold	:	player.jumpHold
private alias object.up			:	player.up
private alias object.down		:	player.down
private alias object.left		:	player.left
private alias object.right		:	player.right

// Object values, not all are used or documented
public  alias object.value0  :	player.rings
private alias object.value18 :	player.sortedDrawOrder
private alias object.value37 :	player.shield	// Current shield the player has, see above constants for what is what
private alias object.value38 :	player.hitboxLeft
private alias object.value39 :	player.hitboxRight
private alias object.value40 :	player.hitboxTop
private alias object.value41 :	player.hitboxBottom
private alias object.value42 :	player.prevGravity

// Death Event related values
private alias object.drawOrder : deathEvent.drawOrder
private alias object.state	   : deathEvent.state
private alias object.value1	   : deathEvent.leftTextPos
private alias object.value2	   : deathEvent.rightTextPos
private alias object.value3	   : deathEvent.timer

// Function declarations
reserve function PlayerObject_ProcessPlayer
reserve function PlayerObject_Blank
reserve function PlayerObject_HandleMovement
reserve function PlayerObject_AirAcceleration
reserve function PlayerObject_HandleAirMovement
reserve function PlayerObject_ResetOnFloor
reserve function PlayerObject_StartJump
reserve function PlayerObject_StartSpindash
reserve function PlayerObject_StartTailsFlight
reserve function PlayerObject_StartKnuxGlide
reserve function PlayerObject_HandleGround
reserve function PlayerObject_HandleBored2
reserve function PlayerObject_HandleAir
reserve function PlayerObject_Unknown
reserve function PlayerObject_HandleRolling
reserve function PlayerObject_RollingJump
reserve function PlayerObject_LookingUp
reserve function PlayerObject_Crouching
reserve function PlayerObject_HandleSpindash
reserve function PlayerObject_HandleTailsFlight
reserve function PlayerObject_KnuxGlideLeft
reserve function PlayerObject_KnuxGlideRight
reserve function PlayerObject_KnuxGlideDrop
reserve function PlayerObject_KnuxGlideSlide
reserve function PlayerObject_KnuxWallClimb
reserve function PlayerObject_KnuxLedgePullUp
reserve function PlayerObject_Hurt
reserve function PlayerObject_Knockback
reserve function PlayerObject_Death
reserve function PlayerObject_Drown
reserve function PlayerObject_CheckTile
reserve function PlayerObject_HandleRollDecel
reserve function PlayerObject_Clinging
reserve function PlayerObject_Waterslide
reserve function PlayerObject_HandleFlyCarry
reserve function PlayerObject_HandleContRun
reserve function PlayerObject_InitReplay
reserve function PlayerObject_RestorePowerup
reserve function PlayerObject_ProcessSuperPalS
reserve function PlayerObject_ProcessSuperPalT
reserve function PlayerObject_ProcessSuperPalK
reserve function PlayerObject_SwitchPhysicsState
reserve function PlayerObject_ProcessSuperState
reserve function PlayerObject_CheckHit
reserve function PlayerObject_BadnikBreak
reserve function PlayerObject_Hit
reserve function PlayerObject_FireHit
reserve function PlayerObject_LightningHit
reserve function PlayerObject_ProjectileHit
reserve function PlayerObject_SpikeHit
reserve function PlayerObject_Kill
reserve function PlayerObject_RollAnimSpd
reserve function PlayerObject_WalkAnimSpd
reserve function PlayerObject_RunAnimSpd
reserve function PlayerObject_RollDecel2
reserve function PlayerObject_Transforming
reserve function PlayerObject_SuperTransform
reserve function PlayerObject_BubbleBounce
reserve function PlayerObject_ShieldAbilities
reserve function PlayerObject_StartFlyCarry

// Static Values
public value PlayerObject_LeaderX = 0;
public value PlayerObject_LeaderY = 0;
public value PlayerObject_SidekickX = 0;
public value PlayerObject_SidekickY = 0;
public value PlayerObject_SuperState = 0;
public value PlayerObject_value1 = 0;
public value PlayerObject_value2 = 0;
public value PlayerObject_value3 = 0;
public value PlayerObject_ReplayTable = 0;
public value PlayerObject_ReplayTablePos = 0;
public value PlayerObject_ReplaySize = 0;
public value PlayerObject_ReplayFrameCnt = 0;
public value PlayerObject_ReplayLength = 0;
private value value13 = 0;
private value value14 = 0;
private value value15 = 0;
private value value16 = 0;
private value value17 = 0;
private value value18 = 0;
private value value19 = 0;

// Tables
public table PlayerObject_SonicSuperPal
	0x2020A0, 0x2040C0, 0x4040E0, 0x6060E0
	0x404080, 0x4060A0, 0x6060E0, 0x8080E0
	0x606060, 0x6080A0, 0x8080E0, 0xA0A0E0
	0x808040, 0x80A0A0, 0xA0A0E0, 0xC0C0E0
	0xA0A040, 0xA0C0A0, 0xC0C0E0, 0xE0E0E0
	0xC0C040, 0xC0E0A0, 0xE0E0E0, 0xE0E0E0
	0xE0E040, 0xE0E0A0, 0xE0E0E0, 0xE0E0E0
	0xE0E060, 0xE0E0E0, 0xE0E0E0, 0xE0E0E0
	0xE0E080, 0xE0E0E0, 0xE0E0E0, 0xE0E0E0
	0xE0E060, 0xE0E0C0, 0xE0E0E0, 0xE0E0E0
	0xE0E040, 0xE0E0A0, 0xE0E0E0, 0xE0E0E0
	0xE0E020, 0xE0E080, 0xE0E0C0, 0xE0E0E0
	0xE0E000, 0xE0E060, 0xE0E0A0, 0xE0E0E0
	0xE0E000, 0xE0E040, 0xE0E080, 0xE0E0C0
	0xE0E000, 0xE0E060, 0xE0E0A0, 0xE0E0E0
	0xE0E000, 0xE0E080, 0xE0E0C0, 0xE0E0E0
end table

public table PlayerObject_SonicSuperAltPal
	0x202080, 0x4040A0, 0x6060C0, 0x8080E0
	0x404060, 0x6060A0, 0x8080E0, 0xA0A0E0
	0x606040, 0x8080A0, 0xA0A0E0, 0xC0C0E0
	0x808040, 0xA0A0A0, 0xC0C0E0, 0xE0E0E0
	0xA0A040, 0xC0C0A0, 0xE0E0E0, 0xE0E0E0
	0xC0C040, 0xE0E0A0, 0xE0E0E0, 0xE0E0E0
	0xE0E040, 0xE0E0A0, 0xE0E0E0, 0xE0E0E0
	0xE0E060, 0xE0E0E0, 0xE0E0E0, 0xE0E0E0
	0xE0E080, 0xE0E0E0, 0xE0E0E0, 0xE0E0E0
	0xE0E060, 0xE0E0C0, 0xE0E0E0, 0xE0E0E0
	0xE0E040, 0xE0E0A0, 0xE0E0E0, 0xE0E0E0
	0xE0E020, 0xE0E080, 0xE0E0C0, 0xE0E0E0
	0xE0E000, 0xE0E060, 0xE0E0A0, 0xE0E0E0
	0xE0E000, 0xE0E040, 0xE0E080, 0xE0E0C0
	0xE0E000, 0xE0E060, 0xE0E0A0, 0xE0E0E0
	0xE0E000, 0xE0E080, 0xE0E0C0, 0xE0E0E0
end table

public table PlayerObject_TailsSuperPal
	0x800000, 0xE08000, 0xE0A000, 0xA06040
	0x800000, 0xE0A020, 0xE0C040, 0xA06040
	0xA06040, 0xE0C040, 0xE0C080, 0xC06040
	0xC06040, 0xE0C080, 0xE0E0A0, 0xE08040
	0xA06040, 0xE0C040, 0xE0C080, 0xC06040
	0x800000, 0xE0A020, 0xE0C040, 0xA06040
end table

public table PlayerObject_TailsSuperAltPal
	0x800000, 0xE08000, 0xE0A000, 0xA06040
	0x800000, 0xE0A020, 0xE0C040, 0xA06040
	0xA06040, 0xE0C040, 0xE0C080, 0xC06040
	0xC06040, 0xE0C080, 0xE0E0A0, 0xE08040
	0xA06040, 0xE0C040, 0xE0C080, 0xC06040
	0x800000, 0xE0A020, 0xE0C040, 0xA06040
end table

public table PlayerObject_KnuxSuperPal
	0x600020, 0xC00020, 0xE04060
	0x802040, 0xE04060, 0xE060A0
	0xA04060, 0xE06080, 0xE080C0
	0xC06080, 0xE080A0, 0xE0A0E0
	0xE080A0, 0xE0A0C0, 0xE0C0E0
	0xE0A0C0, 0xE0C0E0, 0xE0E0E0
	0xE080A0, 0xE0A0C0, 0xE0C0E0
	0xC06080, 0xE080A0, 0xE0A0E0
	0xA04060, 0xE06080, 0xE080C0
	0x802040, 0xE04060, 0xE060A0
end table

public table PlayerObject_KnuxSuperAltPal
	0x600020, 0xC00040, 0xE04080
	0x802040, 0xE04060, 0xE060A0
	0xA04060, 0xE06080, 0xE080C0
	0xC06080, 0xE080A0, 0xE0A0E0
	0xE080A0, 0xE0A0C0, 0xE0C0E0
	0xE0A0C0, 0xE0C0E0, 0xE0E0E0
	0xE080A0, 0xE0A0C0, 0xE0C0E0
	0xC06080, 0xE080A0, 0xE0A0E0
	0xA04060, 0xE06080, 0xE080C0
	0x802040, 0xE04060, 0xE060A0
end table

public table PlayerObject_SonicPhysicsTable
	0x60000, 0xC00,  0x1800, 0x600,  0x8000,  0x600, 0x68000, -0x40000
	0x30000, 0x600,  0xC00,  0x300,  0x4000,  0x300, 0x38000, -0x20000
	0xA0000, 0x3000, 0x6000, 0x1800, 0x10000, 0x600, 0x80000, -0x40000
	0x50000, 0x1800, 0x3000, 0xC00,  0x8000,  0x300, 0x38000, -0x20000
	0xC0000, 0x1800, 0x3000, 0xC00,  0x8000,  0x600, 0x68000, -0x40000
	0x60000, 0xC00,  0x1800, 0x600,  0x4000,  0x300, 0x38000, -0x20000
	0xC0000, 0x1800, 0x3000, 0xC00,  0x8000,  0x600, 0x80000, -0x40000
	0x60000, 0xC00,  0x1800, 0x600,  0x4000,  0x300, 0x38000, -0x20000
end table

public table PlayerObject_TailsPhysicsTable
	0x60000, 0xC00,  0x1800, 0x600,  0x8000,  0x600, 0x68000, -0x40000
	0x30000, 0x600,  0xC00,  0x300,  0x4000,  0x300, 0x38000, -0x20000
	0xA0000, 0x3000, 0x6000, 0x1800, 0x10000, 0x600, 0x80000, -0x40000
	0x50000, 0x1800, 0x3000, 0xC00,  0x8000,  0x300, 0x38000, -0x20000
	0xC0000, 0x1800, 0x3000, 0xC00,  0x8000,  0x600, 0x68000, -0x40000
	0x60000, 0xC00,  0x1800, 0x600,  0x4000,  0x300, 0x38000, -0x20000
	0xC0000, 0x1800, 0x3000, 0xC00,  0x8000,  0x600, 0x80000, -0x40000
	0x60000, 0xC00,  0x1800, 0x600,  0x4000,  0x300, 0x38000, -0x20000
end table

public table PlayerObject_KnuxPhysicsTable
	0x60000, 0xC00,  0x1800, 0x600,  0x8000,  0x600, 0x60000, -0x40000
	0x30000, 0x600,  0xC00,  0x300,  0x4000,  0x300, 0x30000, -0x20000
	0xA0000, 0x3000, 0x6000, 0x1800, 0x10000, 0x600, 0x60000, -0x40000
	0x50000, 0x1800, 0x3000, 0xC00,  0x8000,  0x300, 0x30000, -0x20000
	0xC0000, 0x1800, 0x3000, 0xC00,  0x8000,  0x600, 0x60000, -0x40000
	0x60000, 0xC00,  0x1800, 0x600,  0x4000,  0x300, 0x30000, -0x20000
	0xC0000, 0x1800, 0x3000, 0xC00,  0x8000,  0x600, 0x60000, -0x40000
	0x60000, 0xC00,  0x1800, 0x600,  0x8000,  0x300, 0x30000, -0x20000
end table

function PlayerObject_InitReplay
	PlayerObject_ReplayTablePos = 2
	PlayerObject_ReplayFrameCnt = 1
	currentPlayer = 0
	while currentPlayer < playerCount
		GetTableValue(object[currentPlayer].xpos, 0, PlayerObject_ReplayTable)
		GetTableValue(object[currentPlayer].ypos, 1, PlayerObject_ReplayTable)
		object[currentPlayer].controlMode = -1
		object[currentPlayer].up = 0
		object[currentPlayer].down = 0
		object[currentPlayer].left = 0
		object[currentPlayer].right = 0
		object[currentPlayer].jumpPress = 0
		object[currentPlayer].jumpHold = 0
		object[currentPlayer].value1 = 0
		currentPlayer++
	loop
	screen.cameraX = player[0].ixpos
	screen.cameraY = player[0].iypos
end function


function PlayerObject_RestorePowerup
	switch object[currentPlayer].value37
	case 0
		ResetObjectEntity(arrayPos0, TypeName[Blank Object], 0, 0, 0)
		break
	case 1
		ResetObjectEntity(arrayPos0, blueShieldType, 0, 0, 0)
		object[arrayPos0].priority = PRIORITY_ACTIVE
		object[arrayPos0].inkEffect = INK_ALPHA
		object[arrayPos0].alpha = 160
		break
	case 2
		ResetObjectEntity(arrayPos0, TypeName[Bubble Shield], 0, 0, 0)
		object[arrayPos0].priority = PRIORITY_ACTIVE
		break
	case 3
		ResetObjectEntity(arrayPos0, TypeName[Fire Shield], 0, 0, 0)
		object[arrayPos0].priority = PRIORITY_ACTIVE
		break
	case 4
		ResetObjectEntity(arrayPos0, TypeName[LightningShield], 0, 0, 0)
		object[arrayPos0].priority = PRIORITY_ACTIVE
		break
	end switch
end function


function PlayerObject_ProcessSuperPalS
	if PlayerObject_SuperState == 1
		PlayerObject_value3++
		if PlayerObject_value3 >= 4
			PlayerObject_value3 = 0
			PlayerObject_value2 += 4
			if PlayerObject_value2 >= 64
				PlayerObject_value2 = 24
			end if
		end if
	else
		PlayerObject_value3++
		if PlayerObject_value3 >= 8
			PlayerObject_value3 = 0
			PlayerObject_value2 -= 4
			if PlayerObject_value2 <= 0
				PlayerObject_value2 = 0
				PlayerObject_SuperState = 0
			end if
			if PlayerObject_value2 >= 24
				PlayerObject_value2 = 24
			end if
		end if
	end if
	temp1 = PlayerObject_value2
	GetTableValue(temp0, temp1, PlayerObject_SonicSuperPal)
	SetPaletteEntry(0, 2, temp0)
	GetTableValue(temp0, temp1, PlayerObject_SonicSuperAltPal)
	SetPaletteEntry(1, 2, temp0)
	temp1++
	GetTableValue(temp0, temp1, PlayerObject_SonicSuperPal)
	SetPaletteEntry(0, 3, temp0)
	GetTableValue(temp0, temp1, PlayerObject_SonicSuperAltPal)
	SetPaletteEntry(1, 3, temp0)
	temp1++
	GetTableValue(temp0, temp1, PlayerObject_SonicSuperPal)
	SetPaletteEntry(0, 4, temp0)
	GetTableValue(temp0, temp1, PlayerObject_SonicSuperAltPal)
	SetPaletteEntry(1, 4, temp0)
	temp1++
	GetTableValue(temp0, temp1, PlayerObject_SonicSuperPal)
	SetPaletteEntry(0, 5, temp0)
	GetTableValue(temp0, temp1, PlayerObject_SonicSuperAltPal)
	SetPaletteEntry(1, 5, temp0)
end function


function PlayerObject_ProcessSuperPalT
	if PlayerObject_SuperState == 1
		PlayerObject_value3++
		if PlayerObject_value3 >= 12
			PlayerObject_value3 = 0
			PlayerObject_value2 += 4
			if PlayerObject_value2 >= 24
				PlayerObject_value2 = 0
			end if
		end if
	else
		if PlayerObject_value2 > 12
			FlipSign(PlayerObject_value2)
			PlayerObject_value2 += 24
		end if
		PlayerObject_value3++
		if PlayerObject_value3 >= 12
			PlayerObject_value3 = 0
			PlayerObject_value2 -= 4
			if PlayerObject_value2 <= 0
				PlayerObject_value2 = 0
				PlayerObject_SuperState = 0
			end if
		end if
	end if
	temp1 = PlayerObject_value2
	GetTableValue(temp0, temp1, PlayerObject_TailsSuperPal)
	SetPaletteEntry(0, 13, temp0)
	GetTableValue(temp0, temp1, PlayerObject_TailsSuperAltPal)
	SetPaletteEntry(1, 13, temp0)
	temp1++
	GetTableValue(temp0, temp1, PlayerObject_TailsSuperPal)
	SetPaletteEntry(0, 17, temp0)
	GetTableValue(temp0, temp1, PlayerObject_TailsSuperAltPal)
	SetPaletteEntry(1, 17, temp0)
	temp1++
	GetTableValue(temp0, temp1, PlayerObject_TailsSuperPal)
	SetPaletteEntry(0, 18, temp0)
	GetTableValue(temp0, temp1, PlayerObject_TailsSuperAltPal)
	SetPaletteEntry(1, 18, temp0)
	temp1++
	GetTableValue(temp0, temp1, PlayerObject_TailsSuperPal)
	SetPaletteEntry(0, 16, temp0)
	GetTableValue(temp0, temp1, PlayerObject_TailsSuperAltPal)
	SetPaletteEntry(1, 16, temp0)
end function


function PlayerObject_ProcessSuperPalK
	if PlayerObject_SuperState == 1
		PlayerObject_value3++
		if PlayerObject_value3 >= 12
			PlayerObject_value3 = 9
			PlayerObject_value2 += 3
			if PlayerObject_value2 >= 30
				PlayerObject_value3 = 0
				PlayerObject_value2 = 0
			end if
		end if
	else
		if PlayerObject_value2 > 15
			FlipSign(PlayerObject_value2)
			PlayerObject_value2 += 30
		end if
		PlayerObject_value3++
		if PlayerObject_value3 >= 12
			PlayerObject_value3 = 0
			PlayerObject_value2 -= 3
			if PlayerObject_value2 <= 0
				PlayerObject_value2 = 0
				PlayerObject_SuperState = 0
			end if
		end if
	end if
	temp1 = PlayerObject_value2
	GetTableValue(temp0, temp1, PlayerObject_KnuxSuperPal)
	SetPaletteEntry(0, 26, temp0)
	GetTableValue(temp0, temp1, PlayerObject_KnuxSuperAltPal)
	SetPaletteEntry(1, 26, temp0)
	temp1++
	GetTableValue(temp0, temp1, PlayerObject_KnuxSuperPal)
	SetPaletteEntry(0, 27, temp0)
	GetTableValue(temp0, temp1, PlayerObject_KnuxSuperAltPal)
	SetPaletteEntry(1, 27, temp0)
	temp1++
	GetTableValue(temp0, temp1, PlayerObject_KnuxSuperPal)
	SetPaletteEntry(0, 28, temp0)
	GetTableValue(temp0, temp1, PlayerObject_KnuxSuperAltPal)
	SetPaletteEntry(1, 28, temp0)
end function


function PlayerObject_SwitchPhysicsState
	switch stage.playerListPos
	case 0
	case 3
		temp0 = PlayerObject_SonicPhysicsTable
		break
	case 1
		temp0 = PlayerObject_TailsPhysicsTable
		break
	case 2
		temp0 = PlayerObject_KnuxPhysicsTable
		break
	end switch
	temp1 = 0
	temp2 = 0
	if stage.state != 3
		temp3 = object[currentPlayer].ypos
		temp3 >>= 16
		CheckGreater(temp3, stage.waterLevel)
		temp4 = checkResult
		CheckNotEqual(object[currentPlayer].type, TypeName[Debug Mode])
		temp4 &= checkResult
		if temp4 == 1
			SetBit(temp1, 0, 1)
			object[currentPlayer].value25 = 0x1000
		else
			object[currentPlayer].value25 = 0x3800
		end if
		if PlayerObject_SuperState == 1
			SetBit(temp1, 1, 1)
			temp2 = 2
		end if
		if object[currentPlayer].value6 > 0
			SetBit(temp1, 2, 1)
			temp2 = 1
		end if
		temp1 <<= 3
	end if
	GetTableValue(object[currentPlayer].value20, temp1, temp0)
	temp1++
	GetTableValue(object[currentPlayer].value21, temp1, temp0)
	object[currentPlayer].value22 = object[currentPlayer].value21
	object[currentPlayer].value22 >>= temp2
	temp1++
	GetTableValue(object[currentPlayer].value23, temp1, temp0)
	temp1++
	GetTableValue(object[currentPlayer].value24, temp1, temp0)
	temp1++
	GetTableValue(object[currentPlayer].value9, temp1, temp0)
	temp1++
	GetTableValue(object[currentPlayer].value29, temp1, temp0)
	temp1++
	GetTableValue(object[currentPlayer].value27, temp1, temp0)
	temp1++
	GetTableValue(object[currentPlayer].value28, temp1, temp0)
end function


function PlayerObject_ProcessSuperState
	if PlayerObject_SuperState != 0
		switch stage.playerListPos
		case 0
		case 3
			CallFunction(PlayerObject_ProcessSuperPalS)
			break
		case 1
			CallFunction(PlayerObject_ProcessSuperPalT)
			break
		case 2
			CallFunction(PlayerObject_ProcessSuperPalK)
			break
		end switch
	end if
	if PlayerObject_SuperState == 1
		object.value7 = 60
		PlayerObject_value1++
		if PlayerObject_value1 == 60
			PlayerObject_value1 = 0
			player.rings--
			if player.rings <= 0
				player.rings = 0
				PlayerObject_SuperState = 2
			end if
		end if
	end if
	if PlayerObject_SuperState == 2
		if stage.playerListPos == 0
			LoadAnimation("Sonic.ani")
		end if
		if music.currentTrack == 7
			PlayMusic(0)
		end if
		object.value7 = 0
		currentPlayer = object.entityPos
		if object.state != PlayerObject_Death
			if object.state != PlayerObject_Drown
				arrayPos0 = currentPlayer
				arrayPos0 += playerCount
				CallFunction(PlayerObject_RestorePowerup)
			end if
		end if
		PlayerObject_SuperState = 3
		CallFunction(PlayerObject_SwitchPhysicsState)
	end if
end function


function PlayerObject_CheckHit
	CheckEqual(object[currentPlayer].animation, ANI_JUMPING)
	temp0 = checkResult
	CheckEqual(object[currentPlayer].animation, ANI_SPINDASH)
	temp0 |= checkResult
	CheckEqual(object[currentPlayer].animation, ANI_GLIDING)
	temp0 |= checkResult
	CheckEqual(object[currentPlayer].animation, ANI_GLIDING_STOP)
	temp0 |= checkResult
	CheckNotEqual(object[currentPlayer].value7, 0)
	temp0 |= checkResult
	CheckEqual(object[currentPlayer].animation, ANI_FLYING)
	temp1 = checkResult
	CheckEqual(object[currentPlayer].animation, ANI_FLYINGTIRED)
	temp1 |= checkResult
	CheckEqual(object[currentPlayer].animation, ANI_FLY_LIFT_UP)
	temp1 |= checkResult
	CheckEqual(object[currentPlayer].animation, ANI_FLY_LIFT_DOWN)
	temp1 |= checkResult
	CheckEqual(object[currentPlayer].animation, ANI_FLY_LIFT_TIRED)
	temp1 |= checkResult
	if temp1 == 1
		CheckGreater(object[currentPlayer].ypos, object.ypos)
		temp0 |= checkResult
	end if
	if temp0 == 1
		if object[currentPlayer].gravity == GRAVITY_AIR
			FlipSign(object[currentPlayer].xvel)
			object[currentPlayer].speed = object[currentPlayer].xvel
			object[currentPlayer].yvel += object[currentPlayer].value25
			object[currentPlayer].yvel += object[currentPlayer].value25
			FlipSign(object[currentPlayer].yvel)
		end if
		if object[currentPlayer].animation == ANI_GLIDING
			object[currentPlayer].animation = ANI_GLIDING_DROP
			object[currentPlayer].state = PlayerObject_KnuxGlideDrop
		end if
		checkResult = 1
	else
		if object[currentPlayer].state != PlayerObject_Death
			if object[currentPlayer].value7 == 0
				if object[currentPlayer].value8 == 0
					object[currentPlayer].state = PlayerObject_Hurt
					if object[currentPlayer].xpos > object.xpos
						object[currentPlayer].speed = 0x20000
					else
						object[currentPlayer].speed = -0x20000
					end if
				end if
			end if
		end if
		checkResult = 0
	end if
end function


function PlayerObject_BadnikBreak
	CheckEqual(object[currentPlayer].animation, ANI_JUMPING)
	temp0 = checkResult
	CheckEqual(object[currentPlayer].animation, ANI_SPINDASH)
	temp0 |= checkResult
	CheckEqual(object[currentPlayer].animation, ANI_GLIDING)
	temp0 |= checkResult
	CheckEqual(object[currentPlayer].animation, ANI_GLIDING_STOP)
	temp0 |= checkResult
	CheckNotEqual(object[currentPlayer].value7, 0)
	temp0 |= checkResult
	CheckEqual(object[currentPlayer].animation, ANI_FLYING)
	temp1 = checkResult
	CheckEqual(object[currentPlayer].animation, ANI_FLYINGTIRED)
	temp1 |= checkResult
	CheckEqual(object[currentPlayer].animation, ANI_FLY_LIFT_UP)
	temp1 |= checkResult
	CheckEqual(object[currentPlayer].animation, ANI_FLY_LIFT_DOWN)
	temp1 |= checkResult
	CheckEqual(object[currentPlayer].animation, ANI_FLY_LIFT_TIRED)
	temp1 |= checkResult
	if temp1 == 1
		CheckGreater(object[currentPlayer].ypos, object.ypos)
		temp0 |= checkResult
	end if
	if temp0 == 1
		ResetObjectEntity(object.entityPos, TypeName[Blank Object], 0, object.xpos, object.ypos)
		Rand(checkResult, 32)
		if checkResult > 15
			CreateTempObject(animalType1, TypeName[Blank Object], object.xpos, object.ypos)
		else
			CreateTempObject(animalType2, TypeName[Blank Object], object.xpos, object.ypos)
		end if
		object[tempObjectPos].priority = PRIORITY_UNKNOWN
		CreateTempObject(TypeName[Smoke Puff], 0, object.xpos, object.ypos)
		object[tempObjectPos].drawOrder = 4
		CreateTempObject(TypeName[Object Score], object[currentPlayer].value19, object.xpos, object.ypos)
		object[tempObjectPos].drawOrder = 4
		PlaySfx(SfxName[Destroy], 0)
		if object[currentPlayer].yvel > 0
			if object[currentPlayer].ypos >= object.ypos
				object[currentPlayer].yvel -= 0x10000
			else
				object[currentPlayer].yvel += object[currentPlayer].value25
				object[currentPlayer].yvel += object[currentPlayer].value25
				FlipSign(object[currentPlayer].yvel)
			end if
		else
			object[currentPlayer].yvel += 0x10000
		end if
		temp1 = arrayPos0
		if options.vsMode == 0
			temp0 = currentPlayer
			currentPlayer = 0
			arrayPos0 = 22
		else
			arrayPos0 = 22
			arrayPos0 += currentPlayer
		end if
		switch object[currentPlayer].value19
		case 0
			player.score += 100
			break
		case 1
			player.score += 200
			break
		case 2
			player.score += 500
			break
		case 3
		case 4
		case 5
		case 6
		case 7
		case 8
		case 9
		case 10
		case 11
		case 12
		case 13
		case 14
			player.score += 1000
			break
		case 15
			player.score += 0x2710
			break
		end switch
		if object[currentPlayer].value19 < 15
			object[currentPlayer].value19++
		end if
		if options.vsMode == 0
			currentPlayer = temp0
		end if
		arrayPos0 = temp1
	else
		if object[currentPlayer].state != PlayerObject_Death
			if object[currentPlayer].value7 == 0
				if object[currentPlayer].value8 == 0
					object[currentPlayer].state = PlayerObject_Hurt
					if object[currentPlayer].xpos > object.xpos
						object[currentPlayer].speed = 0x20000
					else
						object[currentPlayer].speed = -0x20000
					end if
				end if
			end if
		end if
	end if
end function


function PlayerObject_Hit
	if object[currentPlayer].state != PlayerObject_Death
		arrayPos0 = object[currentPlayer].entityPos
		arrayPos0 += playerCount
		if object[currentPlayer].value7 == 0
			if object[currentPlayer].value8 == 0
				object[currentPlayer].state = PlayerObject_Hurt
				if object[currentPlayer].xpos > object.xpos
					object[currentPlayer].speed = 0x20000
				else
					object[currentPlayer].speed = -0x20000
				end if
			end if
		end if
	end if
end function


function PlayerObject_FireHit
	if object[currentPlayer].value37 != 3
		if object[currentPlayer].state != PlayerObject_Death
			arrayPos0 = object[currentPlayer].entityPos
			arrayPos0 += playerCount
			if object[currentPlayer].value7 == 0
				if object[currentPlayer].value8 == 0
					object[currentPlayer].state = PlayerObject_Hurt
					if object[currentPlayer].xpos > object.xpos
						object[currentPlayer].speed = 0x20000
					else
						object[currentPlayer].speed = -0x20000
					end if
				end if
			end if
		end if
	end if
end function


function PlayerObject_LightningHit
	if object[currentPlayer].value37 != 4
		if object[currentPlayer].state != PlayerObject_Death
			arrayPos0 = object[currentPlayer].entityPos
			arrayPos0 += playerCount
			if object[currentPlayer].value7 == 0
				if object[currentPlayer].value8 == 0
					object[currentPlayer].state = PlayerObject_Hurt
					if object[currentPlayer].xpos > object.xpos
						object[currentPlayer].speed = 0x20000
					else
						object[currentPlayer].speed = -0x20000
					end if
				end if
			end if
		end if
	end if
end function


function PlayerObject_ProjectileHit
	if object[currentPlayer].value37 > 1
		temp0 = object[currentPlayer].xpos
		temp0 -= object.xpos
		temp1 = object[currentPlayer].ypos
		temp1 -= object.ypos
		ATan2(temp2, temp0, temp1)
		Sin256(temp0, temp2)
		Cos256(temp1, temp2)
		object.xvel = temp1
		object.xvel *= -0x800
		object.yvel = temp0
		object.yvel *= -0x800
	else
		if object[currentPlayer].state != PlayerObject_Death
			arrayPos0 = object[currentPlayer].entityPos
			arrayPos0 += playerCount
			if object[currentPlayer].value7 == 0
				if object[currentPlayer].value8 == 0
					object[currentPlayer].state = PlayerObject_Hurt
					if object[currentPlayer].xpos > object.xpos
						object[currentPlayer].speed = 0x20000
					else
						object[currentPlayer].speed = -0x20000
					end if
				end if
			end if
		end if
	end if
end function


function PlayerObject_SpikeHit
	if object[currentPlayer].state != PlayerObject_Death
		arrayPos0 = object[currentPlayer].entityPos
		arrayPos0 += playerCount
		if object[currentPlayer].value7 == 0
			if object[currentPlayer].state != PlayerObject_Hurt
				if object[currentPlayer].state != PlayerObject_Knockback
					temp0 = options.spikeBehavior
					CheckEqual(object[currentPlayer].value8, 0)
					temp0 |= checkResult
					if temp0 == 1
						if object[currentPlayer].value8 == 0
							object[currentPlayer].value8 = 2
						end if
						object[currentPlayer].state = PlayerObject_Hurt
						if object[currentPlayer].xpos > object.xpos
							object[currentPlayer].speed = 0x20000
						else
							object[currentPlayer].speed = -0x20000
						end if
					end if
				end if
			end if
		end if
	end if
end function


function PlayerObject_Kill
	PlaySfx(SfxName[Hurt], 0)
	object[currentPlayer].speed = 0
	object[currentPlayer].xvel = 0
	object[currentPlayer].yvel = -0x68000
	object[currentPlayer].state = PlayerObject_Death
	object[currentPlayer].animation = ANI_DYING
	object[currentPlayer].tileCollisions = 0
	object[currentPlayer].interaction = 0
	object[currentPlayer].value8 = 0
	object[currentPlayer].visible = 1
	player[currentPlayer].sortedDrawOrder = 6
	if options.vsMode == 0
		if currentPlayer == 0
			object[currentPlayer].priority = PRIORITY_ACTIVE_PAUSED
			if object[1].type == TypeName[Player 2 Object]
				object[1].priority = PRIORITY_ACTIVE_PAUSED
			end if
			screen.cameraEnabled = 0
			stage.state = 3
		end if
	else
		if currentPlayer == screen.cameraTarget
			screen.cameraEnabled = 0
		end if
	end if
	arrayPos0 = currentPlayer
	arrayPos0 += playerCount
	if object[arrayPos0].type == invincibilityType
		object[arrayPos0].propertyValue = 3
	end if
	object[arrayPos0].type = TypeName[Blank Object]
	object[currentPlayer].value37 = 0
end function


function PlayerObject_ProcessPlayer
	if options.attractMode == 0
		if object.controlMode == 0
			CheckTouchRect(0, 96, screen.xcenter, screen.ysize)
			if checkResult > -1
				arrayPos0 = checkResult
				temp0 = touchscreen[arrayPos0].xpos
				temp0 -= saveRAM[39]
				temp1 = touchscreen[arrayPos0].ypos
				temp1 -= saveRAM[40]
				ATan2(temp2, temp0, temp1)
				temp2 += 32
				temp2 &= 255
				temp2 >>= 6
				switch temp2
				case 0
					inputDown.right = 1
					break
				case 1
					inputDown.down = 1
					break
				case 2
					inputDown.left = 1
					break
				case 3
					inputDown.up = 1
					break
				end switch
			end if
			CheckTouchRect(screen.xcenter, 96, screen.xsize, 240)
			if checkResult > -1
				inputDown.buttonA = 1
			end if
			if touchJump == 0
				inputPress.buttonA |= inputDown.buttonA
			end if
			touchJump = inputDown.buttonA
			if stage.debugMode == 1
				CheckTouchRect(0, 0, 112, 56)
				if checkResult > -1
					inputDown.buttonB = 1
				end if
				if touchDebug == 0
					inputPress.buttonB |= inputDown.buttonB
				end if
				touchDebug = inputDown.buttonB
			end if
			CheckTouchRect(240, 0, screen.xsize, 40)
			if checkResult > -1
				if options.vsMode == 0
					PlaySfx(SfxName[Menu Back], 0)
					StopSfx(SfxName[Flying])
					StopSfx(SfxName[Tired])
					engine.state = 5
				end if
			end if
			if inputPress.start == 1
				if options.vsMode == 0
					PlaySfx(SfxName[Menu Back], 0)
					StopSfx(SfxName[Flying])
					StopSfx(SfxName[Tired])
					engine.state = 5
				end if
			end if
		end if
		ProcessObjectControl()
		if options.vsMode == 1
			CallNativeFunction2(SendEntity, 0, 0)
		end if
	else
		if credits.screen == 0
			CheckTouchRect(0, 0, screen.xsize, screen.ysize)
			if inputPress.start == 1
				checkResult = 0
			end if
			if checkResult > -1
				if PlayerObject_ReplayLength > 1
					PlayerObject_ReplayLength = 1
				end if
			end if
			if inputPress.start == 1
				if PlayerObject_ReplayLength > 1
					PlayerObject_ReplayLength = 1
				end if
			end if
		end if
		if object.controlMode == 0
			PlayerObject_ReplayFrameCnt--
			if PlayerObject_ReplayFrameCnt < 1
				if PlayerObject_ReplayTablePos < PlayerObject_ReplaySize
					GetTableValue(temp0, PlayerObject_ReplayTablePos, PlayerObject_ReplayTable)
					GetBit(object.up, temp0, 0)
					GetBit(object.down, temp0, 1)
					GetBit(object.left, temp0, 2)
					GetBit(object.right, temp0, 3)
					GetBit(object.jumpPress, temp0, 4)
					GetBit(object.jumpHold, temp0, 5)
					PlayerObject_ReplayTablePos++
					GetTableValue(PlayerObject_ReplayFrameCnt, PlayerObject_ReplayTablePos, PlayerObject_ReplayTable)
					PlayerObject_ReplayTablePos++
				end if
			else
				if object.jumpPress == 1
					object.jumpPress = 0
				end if
			end if
			if PlayerObject_ReplayLength > 0
				PlayerObject_ReplayLength--
				if PlayerObject_ReplayLength < 1
					ResetObjectEntity(11, TypeName[Title Card], 0, 0, 0)
					object[11].state = 8
					object[11].priority = PRIORITY_ACTIVE
					object[11].drawOrder = 6
					object.value7 = 80
					screen.cameraEnabled = 0
				end if
			end if
		end if
	end if
	if object.value6 > 0
		object.value6--
		if object.value6 < 1
			currentPlayer = object.entityPos
			CallFunction(PlayerObject_SwitchPhysicsState)
			temp0 = 0
			foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
				temp0 += object[currentPlayer].value6
			next
			if temp0 == 0
				if SlowDownMusic != 0
					CallFunction(SlowDownMusic)
				end if
			end if
			object.value6 = 0
		end if
	end if
	if object.state != PlayerObject_Knockback
		if object.value8 > 0
			object.value8--
			GetBit(temp0, object.value8, 2)
			if temp0 == 1
				object.visible = 0
			else
				object.visible = 1
			end if
		end if
	end if
	if object.value7 > 0
		object.value7--
		if object.value7 == 0
			temp0 = 0
			foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
				temp0 += object[currentPlayer].value7
			next
			if temp0 == 0
				if music.currentTrack == 2
					PlayMusic(0)
				end if
			end if
			if object[+playerCount].type == invincibilityType
				currentPlayer = object.entityPos
				arrayPos0 = currentPlayer
				arrayPos0 += playerCount
				CallFunction(PlayerObject_RestorePowerup)
			end if
		end if
	end if
	if object.state != PlayerObject_LookingUp
		if object.state != PlayerObject_Crouching
			if object.lookPosY > 0
				object.lookPosY -= 2
			end if
			if object.lookPosY < 0
				object.lookPosY += 2
			end if
		end if
	end if
	if object.value11 > 0
		object.value11--
		if object.value11 == 0
			if object.entityPos == screen.cameraTarget
				screen.cameraStyle = 0
			end if
		end if
	end if
	if object.state != PlayerObject_HandleTailsFlight
		if object.value26 != 0
			StopSfx(SfxName[Flying])
			StopSfx(SfxName[Tired])
			object.value26 = 0
		end if
	end if
end function


function PlayerObject_Blank
	checkResult = 0
end function


function PlayerObject_RollAnimSpd
	if object.propertyValue == 1
		object.value5 = 120
	else
		object.value5 = object.speed
		if object.value5 < 0
			FlipSign(object.value5)
		end if
		object.value5 *= 240
		object.value5 /= 0x60000
		object.value5 += 48
	end if
end function


function PlayerObject_WalkAnimSpd
	object.animationSpeed = object.speed
	if object.animationSpeed < 0
		FlipSign(object.animationSpeed)
	end if
	object.animationSpeed *= 60
	object.animationSpeed /= 0x60000
	object.animationSpeed += 20
end function


function PlayerObject_RunAnimSpd
	object.animationSpeed = object.speed
	if object.animationSpeed < 0
		FlipSign(object.animationSpeed)
	end if
	object.animationSpeed *= 80
	object.animationSpeed /= 0x60000
end function


function PlayerObject_HandleMovement
	if object.controlLock > 0
		object.controlLock--
		Sin256(temp0, object.angle)
		temp0 *= 0x2000
		temp0 >>= 8
		object.speed += temp0
	else
		if object.left == 1
			temp0 = object.value20
			FlipSign(temp0)
			if object.speed > temp0
				if object.speed > 0
					if object.collisionMode == CMODE_FLOOR
						if object.speed > 0x40000
							object.value14 = 16
						end if
					end if
					if object.speed < object.value9
						object.speed = object.value9
						FlipSign(object.speed)
						object.value14 = 0
					else
						object.speed -= object.value9
					end if
				else
					object.speed -= object.value21
					object.value14 = 0
				end if
			end if
			if object.speed <= 0
				object.direction = FLIP_X
			end if
		end if
		if object.right == 1
			if object.speed < object.value20
				if object.speed < 0
					if object.collisionMode == CMODE_FLOOR
						if object.speed < -0x40000
							object.value14 = 16
						end if
					end if
					temp0 = object.value9
					FlipSign(temp0)
					if object.speed > temp0
						object.speed = object.value9
						object.value14 = 0
					else
						object.speed += object.value9
					end if
				else
					object.speed += object.value21
					object.value14 = 0
				end if
			end if
			if object.speed >= 0
				object.direction = FLIP_NONE
			end if
		end if
		temp0 = object.left
		temp0 |= object.right
		if temp0 == 0
			if object.speed > 0
				object.speed -= object.value22
				if object.speed < 0
					object.speed = 0
				end if
			else
				object.speed += object.value22
				if object.speed > 0
					object.speed = 0
				end if
			end if
			if object.speed > 0x2000
				Sin256(temp0, object.angle)
				temp0 *= 0x2000
				temp0 >>= 8
				object.speed += temp0
			end if
			if object.speed < -0x2000
				Sin256(temp0, object.angle)
				temp0 *= 0x2000
				temp0 >>= 8
				object.speed += temp0
			end if
			if object.angle > 192
				if object.angle < 228
					if object.speed > -0x10000
						if object.speed < 0x10000
							object.controlLock = 30
						end if
					end if
				end if
			end if
			if object.angle > 28
				if object.angle < 64
					if object.speed > -0x10000
						if object.speed < 0x10000
							object.controlLock = 30
						end if
					end if
				end if
			end if
		else
			Sin256(temp0, object.angle)
			temp0 *= 0x2000
			temp0 >>= 8
			object.speed += temp0
			if object.right == 1
				if object.left == 0
					if object.angle > 192
						if object.angle < 228
							if object.speed < 0x28000
								if object.speed > -0x20000
									object.controlLock = 30
								end if
							end if
						end if
					end if
				end if
			else
				if object.left == 1
					if object.angle > 28
						if object.angle < 64
							if object.speed > -0x28000
								if object.speed < 0x20000
									object.controlLock = 30
								end if
							end if
						end if
					end if
				end if
			end if
		end if
		if options.speedCap == 1
			if object.left == 1
				temp0 = object.value20
				FlipSign(temp0)
				if object.speed < temp0
					object.speed = temp0
				end if
			end if
			if object.right == 1
				if object.speed > object.value20
					object.speed = object.value20
				end if
			end if
		end if
	end if
	switch object.collisionMode
	case 1
		if object.angle <= 192
			if object.speed > -0x20000
				if object.speed < 0x20000
					object.gravity = GRAVITY_AIR
					object.angle = 0
					object.collisionMode = CMODE_FLOOR
					object.speed = object.xvel
				end if
			end if
		end if
		break
	case 2
		if object.speed > -0x20000
			if object.speed < 0x20000
				object.gravity = GRAVITY_AIR
				object.angle = 0
				object.collisionMode = CMODE_FLOOR
				object.speed = object.xvel
			end if
		end if
		break
	case 3
		if object.angle >= 64
			if object.speed > -0x20000
				if object.speed < 0x20000
					object.gravity = GRAVITY_AIR
					object.angle = 0
					object.collisionMode = CMODE_FLOOR
					object.speed = object.xvel
				end if
			end if
		end if
		break
	end switch
end function


function PlayerObject_AirAcceleration
	if object.yvel > -0x40000
		if object.yvel < 0
			temp0 = object.speed
			temp0 >>= 5
			object.speed -= temp0
		end if
	end if
	temp0 = object.value20
	FlipSign(temp0)
	if object.speed > temp0
		if object.left == 1
			object.speed -= object.value23
			object.direction = FLIP_X
		end if
	else
		if object.left == 1
			object.direction = FLIP_X
		end if
	end if
	if object.speed < object.value20
		if object.right == 1
			object.speed += object.value23
			object.direction = FLIP_NONE
		end if
	else
		if object.right == 1
			object.direction = FLIP_NONE
		end if
	end if
	if options.airSpeedCap == 1
		if object.left == 1
			temp0 = object.value20
			FlipSign(temp0)
			if object.speed < temp0
				object.speed = temp0
			end if
		end if
		if object.right == 1
			if object.speed > object.value20
				object.speed = object.value20
			end if
		end if
	end if
end function


function PlayerObject_RollDecel2
	if object.right == 1
		if object.speed < 0
			object.speed += object.value31
		end if
	end if
	if object.left == 1
		if object.speed > 0
			object.speed -= object.value31
		end if
	end if
	temp1 = object.speed
	if object.speed > 0
		object.speed -= object.value29
		Sin256(temp0, object.angle)
		if temp0 > 0
			Sin256(temp0, object.angle)
			temp0 *= 0x5000
		else
			Sin256(temp0, object.angle)
			temp0 *= 0x1400
		end if
		temp0 >>= 8
		object.speed += temp0
		if object.speed > 0x120000
			object.speed = 0x120000
		end if
	else
		object.speed += object.value29
		Sin256(temp0, object.angle)
		if temp0 < 0
			Sin256(temp0, object.angle)
			temp0 *= 0x5000
		else
			Sin256(temp0, object.angle)
			temp0 *= 0x1400
		end if
		temp0 >>= 8
		object.speed += temp0
		if object.speed < -0x120000
			object.speed = -0x120000
		end if
	end if
	switch object.collisionMode
	case 0
	case 2
		if temp1 > 0
			if object.speed < 0
				object.speed = 0
				object.state = PlayerObject_HandleGround
			end if
		else
			if object.speed > 0
				object.speed = 0
				object.state = PlayerObject_HandleGround
			end if
		end if
		break
	case 1
		if object.angle < 193
			if temp1 > 0
				if object.speed < 0x20000
					object.gravity = GRAVITY_AIR
					object.xvel = 0
					object.speed = 0
				end if
			end if
		end if
		break
	case 3
		if object.angle > 63
			if temp1 < 0
				if object.speed > -0x20000
					object.gravity = GRAVITY_AIR
					object.xvel = 0
					object.speed = 0
				end if
			end if
		end if
		break
	end switch
end function


function PlayerObject_HandleAirMovement
	object.scrollTracking = 1
	object.yvel += object.value25
	if object.yvel < object.value28
		if object.jumpHold == 0
			if object.value1 > 0
				object.yvel = object.value28
				temp0 = object.speed
				temp0 >>= 5
				object.speed -= temp0
			end if
		end if
	end if
	object.xvel = object.speed
	if object.rotation < 256
		if object.rotation > 0
			object.rotation -= 4
		else
			object.rotation = 0
		end if
	else
		if object.rotation < 512
			object.rotation += 4
		else
			object.rotation = 0
		end if
	end if
	object.collisionMode = CMODE_FLOOR
	if object.animation == ANI_JUMPING
		object.animationSpeed = object.value5
	end if
end function


function PlayerObject_ResetOnFloor
	object.scrollTracking = 0
	Cos256(temp0, object.angle)
	temp0 *= object.speed
	temp0 >>= 8
	object.xvel = temp0
	Sin256(temp0, object.angle)
	temp0 *= object.speed
	temp0 >>= 8
	object.yvel = temp0
end function


function PlayerObject_StartJump
	temp1 = 0
	if object.collisionMode == CMODE_FLOOR
		temp6 = object.xpos
		temp7 = object.ypos
		temp0 = object.collisionTop
		temp0 -= 2
		ObjectTileCollision(CSIDE_ROOF, 0, temp0, object.collisionPlane)
		temp1 = checkResult
		object.xpos = temp6
		object.ypos = temp7
		temp0 = object.collisionBottom
		if object.animation != ANI_JUMPING
			object.iypos -= object.value30
			temp0 += object.value30
		end if
		ObjectTileCollision(CSIDE_FLOOR, 0, temp0, object.collisionPlane)
	end if
	if temp1 == 0
		object.controlLock = 0
		object.gravity = GRAVITY_AIR
		temp1 = object.value27
		temp1 += object.value25
		Sin256(object.xvel, object.angle)
		object.xvel *= temp1
		Cos256(temp0, object.angle)
		temp0 *= object.speed
		object.xvel += temp0
		object.xvel >>= 8
		Sin256(object.yvel, object.angle)
		object.yvel *= object.speed
		Cos256(temp0, object.angle)
		temp0 *= temp1
		object.yvel -= temp0
		object.yvel >>= 8
		object.speed = object.xvel
		object.scrollTracking = 1
		object.animation = ANI_JUMPING
		object.angle = 0
		object.collisionMode = CMODE_FLOOR
		object.value1 = 1
		CallFunction(PlayerObject_RollAnimSpd)
		if object.state == PlayerObject_HandleRolling
			object.state = PlayerObject_RollingJump
		else
			object.state = PlayerObject_HandleAir
		end if
		PlaySfx(SfxName[Jump], 0)
		object.value34 = 1
		object.value35 = 1
	end if
end function


function PlayerObject_StartSpindash
	object.state = PlayerObject_HandleSpindash
	object.animation = ANI_SPINDASH
	object.value2 = 0
	PlaySfx(SfxName[Charge], 0)
	CreateTempObject(TypeName[Dust Puff], object.entityPos, object.xpos, object.ypos)
	object[tempObjectPos].iypos = object.collisionBottom
	object[tempObjectPos].ypos += object.ypos
	object[tempObjectPos].frame = 4
	object[tempObjectPos].drawOrder = 4
	object[tempObjectPos].direction = object.direction
end function


function PlayerObject_Transforming
	object.value34 = 1
	object.value1--
	if object.value1 == 0
		object.state = PlayerObject_HandleAir
		object.animation = ANI_WALKING
	end if
end function


function PlayerObject_SuperTransform
	if stage.timeEnabled == 1
		arrayPos0 = currentPlayer
		arrayPos0 += playerCount
		ResetObjectEntity(arrayPos0, TypeName[Super Spark], 0, object[0].xpos, object[0].ypos)
		object[arrayPos0].priority = PRIORITY_ACTIVE
		PlaySfx(SfxName[Transform], 0)
		PlayMusic(7)
		PlayerObject_SuperState = 1
		object[currentPlayer].value7 = 60
		object[currentPlayer].value8 = 0
		object[currentPlayer].visible = 1
		CallFunction(PlayerObject_SwitchPhysicsState)
		if stage.playerListPos == 0
			LoadAnimation("SuperSonic.ani")
		end if
		object[currentPlayer].state = PlayerObject_Transforming
		object[currentPlayer].value34 = 1
		object[currentPlayer].animation = ANI_SUPER_TRANSFORM
		object[currentPlayer].value1 = 24
	end if
end function


function PlayerObject_BubbleBounce
	CallFunction(PlayerObject_AirAcceleration)
	CheckNotEqual(object.value37, 2)
	temp0 = checkResult
	CheckNotEqual(object.value7, 0)
	temp0 |= checkResult
	CheckEqual(PlayerObject_SuperState, 1)
	temp0 |= checkResult
	if temp0 == 1
		object.state = PlayerObject_HandleAir
	else
		if object.gravity == GRAVITY_AIR
			CallFunction(PlayerObject_HandleAirMovement)
		else
			object.value35 = 1
			object.gravity = GRAVITY_AIR
			if object.value27 == 0x38000
				temp1 = -0x40000
			else
				temp1 = -0x78000
			end if
			temp1 += object.value25
			Sin256(object.xvel, object.angle)
			object.xvel *= temp1
			Cos256(temp0, object.angle)
			temp0 *= object.speed
			object.xvel += temp0
			object.xvel >>= 8
			Sin256(object.yvel, object.angle)
			object.yvel *= object.speed
			Cos256(temp0, object.angle)
			temp0 *= temp1
			object.yvel = temp0
			object.yvel >>= 8
			object.speed = object.xvel
			object.scrollTracking = 1
			object.animation = ANI_JUMPING
			object.angle = 0
			object.collisionMode = CMODE_FLOOR
			object.value1 = 1
			CallFunction(PlayerObject_RollAnimSpd)
			object.state = PlayerObject_HandleAir
			PlaySfx(SfxName[Bubble Bounce], 0)
			object[+playerCount].state = 4
		end if
	end if
end function


function PlayerObject_ShieldAbilities
	if object.jumpPress == 1
		CheckEqual(specialStage.emeralds, 127)
		temp0 = checkResult
		CheckGreater(player.rings, 49)
		temp0 &= checkResult
		CheckNotEqual(PlayerObject_SuperState, 1)
		temp0 &= checkResult
		CheckNotEqual(object[30].type, TypeName[Act Finish])
		temp0 &= checkResult
		if temp0 == 1
			currentPlayer = object.entityPos
			CallFunction(PlayerObject_SuperTransform)
		else
			CheckEqual(object.value7, 0)
			temp0 = checkResult
			CheckNotEqual(PlayerObject_SuperState, 1)
			temp0 &= checkResult
			if temp0 == 1
				switch object.value37
				case 0
					temp0 = options.shieldType
					temp0 &= 1
					if temp0 > 0
						PlaySfx(SfxName[Insta Shield], 0)
						if object[+playerCount].type == TypeName[Blank Object]
							currentPlayer = object.entityPos
							arrayPos0 = currentPlayer
							arrayPos0 += playerCount
							ResetObjectEntity(arrayPos0, TypeName[Insta Shield], 0, 0, 0)
							object[arrayPos0].priority = PRIORITY_ACTIVE
						end if
						object.value35 = 2
						object[+playerCount].state = 1
						if object.state == PlayerObject_RollingJump
							object.state = PlayerObject_HandleAir
						end if
					end if
					break
				case 1
					break
				case 2
					PlaySfx(SfxName[Bubble Bounce], 0)
					object.yvel = 0x80000
					object.xvel = 0
					object.speed = object.xvel
					object.value35 = 2
					object.state = PlayerObject_BubbleBounce
					object[+playerCount].state = 2
					break
				case 3
					PlaySfx(SfxName[Fire Dash], 0)
					GetBit(temp0, object.direction, 0)
					if temp0 == 0
						object.xvel = 0x80000
					else
						object.xvel = -0x80000
					end if
					object.speed = object.xvel
					object.yvel = 0
					object.value35 = 2
					if object.entityPos == screen.cameraTarget
						object.value11 = 15
						screen.cameraStyle = 4
					end if
					if object.state == PlayerObject_RollingJump
						object.state = PlayerObject_HandleAir
					end if
					object[+playerCount].state = 2
					object[+playerCount].direction = object.direction
					break
				case 4
					PlaySfx(SfxName[Lightning Jump], 0)
					object.yvel = -0x58000
					object.value35 = 2
					CreateTempObject(TypeName[Lightning Spark], 0, object.xpos, object.ypos)
					object[tempObjectPos].xvel = -0x20000
					object[tempObjectPos].yvel = -0x20000
					CreateTempObject(TypeName[Lightning Spark], 0, object.xpos, object.ypos)
					object[tempObjectPos].xvel = 0x20000
					object[tempObjectPos].yvel = -0x20000
					CreateTempObject(TypeName[Lightning Spark], 0, object.xpos, object.ypos)
					object[tempObjectPos].xvel = -0x20000
					object[tempObjectPos].yvel = 0x20000
					CreateTempObject(TypeName[Lightning Spark], 0, object.xpos, object.ypos)
					object[tempObjectPos].xvel = 0x20000
					object[tempObjectPos].yvel = 0x20000
					if object.state == PlayerObject_RollingJump
						object.state = PlayerObject_HandleAir
					end if
					break
				end switch
			end if
		end if
	end if
end function


function PlayerObject_StartTailsFlight
	if object.jumpPress == 1
		CheckEqual(specialStage.emeralds, 127)
		temp0 = checkResult
		CheckGreater(player.rings, 49)
		temp0 &= checkResult
		CheckNotEqual(PlayerObject_SuperState, 1)
		temp0 &= checkResult
		CheckEqual(options.superTails, 1)
		temp0 &= checkResult
		if temp0 == 1
			currentPlayer = object.entityPos
			CallFunction(PlayerObject_SuperTransform)
		else
			object.value1 = 0
			object.state = PlayerObject_HandleTailsFlight
			object.value26 = 0x800
			if object.value25 == 0x3800
				PlaySfx(SfxName[Flying], 1)
				object.animation = ANI_FLYING
			else
				object.animation = ANI_SWIMMING
			end if
		end if
	end if
end function


function PlayerObject_StartKnuxGlide
	if object.jumpPress == 1
		CheckEqual(specialStage.emeralds, 127)
		temp0 = checkResult
		CheckGreater(player.rings, 49)
		temp0 &= checkResult
		CheckNotEqual(PlayerObject_SuperState, 1)
		temp0 &= checkResult
		if temp0 == 1
			currentPlayer = object.entityPos
			CallFunction(PlayerObject_SuperTransform)
		else
			object.speed = 0x40000
			if object.yvel < 0
				object.yvel = 0
			end if
			if object.direction == FLIP_NONE
				object.state = PlayerObject_KnuxGlideRight
				object.xvel = 0x40000
				object.value1 = 0
			else
				object.state = PlayerObject_KnuxGlideLeft
				object.xvel = -0x40000
				object.value1 = 256
			end if
			object.animation = ANI_GLIDING
			object.frame = 2
		end if
	end if
end function


function PlayerObject_HandleGround
	if object.animation != ANI_SKIDDING
		temp7 = 1
	else
		temp7 = 0
	end if
	CallFunction(PlayerObject_HandleMovement)
	if object.gravity == GRAVITY_AIR
		object.state = PlayerObject_HandleAir
		CallFunction(PlayerObject_HandleAirMovement)
	else
		CallFunction(PlayerObject_ResetOnFloor)
		if object.speed == 0
			if object.collisionMode == CMODE_FLOOR
				switch object.propertyValue
				case 0
					if PlayerObject_SuperState == 1
						object.animation = ANI_STOPPED
						object.value1 = 0
						if object.floorSensorC == 0
							if object.floorSensorR == 0
								object.animation = ANI_FLAILING1
								object.direction = FLIP_NONE
							end if
							if object.floorSensorL == 0
								object.animation = ANI_FLAILING1
								object.direction = FLIP_X
							end if
						end if
					else
						if object.value1 < 240
							object.animation = ANI_STOPPED
							object.value1++
						else
							object.animation = ANI_WAITING
							object.value1++
							if object.value1 == 0x4B0
								object.value1 = 0
								object.state = PlayerObject_HandleBored2
							end if
						end if
						if object.direction == FLIP_NONE
							if object.floorSensorR == 0
								if object.floorSensorC == 0
									object.value1 = 0
									if object.floorSensorLC == 0
										object.animation = ANI_FLAILING3
									else
										object.animation = ANI_FLAILING1
									end if
								end if
							else
								if object.floorSensorL == 0
									if object.floorSensorC == 0
										object.value1 = 0
										object.animation = ANI_FLAILING2
									end if
								end if
							end if
						else
							if object.floorSensorL == 0
								if object.floorSensorC == 0
									object.value1 = 0
									if object.floorSensorRC == 0
										object.animation = ANI_FLAILING3
									else
										object.animation = ANI_FLAILING1
									end if
								end if
							else
								if object.floorSensorR == 0
									if object.floorSensorC == 0
										object.value1 = 0
										object.animation = ANI_FLAILING2
									end if
								end if
							end if
						end if
					end if
					break
				case 1
					if object.value1 < 240
						object.animation = ANI_STOPPED
						object.value1++
					else
						object.animation = ANI_WAITING
					end if
					if object.floorSensorC == 0
						if object.floorSensorR == 0
							object.value1 = 0
							object.animation = ANI_FLAILING1
							object.direction = FLIP_NONE
						end if
						if object.floorSensorL == 0
							object.value1 = 0
							object.animation = ANI_FLAILING1
							object.direction = FLIP_X
						end if
					end if
					break
				case 2
					if object.value1 < 240
						object.animation = ANI_STOPPED
						object.value1++
					else
						object.animation = ANI_WAITING
						object.value1++
						if object.value1 == 834
							object.value1 = 0
							object.animation = ANI_STOPPED
						end if
					end if
					if object.floorSensorC == 0
						if object.floorSensorR == 0
							object.value1 = 0
							object.animation = ANI_FLAILING1
							if object.direction == FLIP_X
								object.prevAnimation = ANI_FLAILING1
								object.frame = 4
								object.animationTimer = 0
								object.animationSpeed = 0
							end if
							object.direction = FLIP_NONE
						end if
						if object.floorSensorL == 0
							object.value1 = 0
							object.animation = ANI_FLAILING1
							if object.direction == FLIP_NONE
								object.prevAnimation = ANI_FLAILING1
								object.frame = 4
								object.animationTimer = 0
								object.animationSpeed = 0
							end if
							object.direction = FLIP_X
						end if
					end if
					break
				end switch
			end if
		else
			object.value1 = 0
			if object.speed > 0
				if object.speed < 0x5F5C2
					object.animation = ANI_WALKING
					CallFunction(PlayerObject_WalkAnimSpd)
				else
					if object.speed > 0x9FFFF
						object.animation = ANI_PEELOUT
					else
						object.animation = ANI_RUNNING
					end if
					CallFunction(PlayerObject_RunAnimSpd)
				end if
			else
				if object.speed > -0x5F5C2
					object.animation = ANI_WALKING
					CallFunction(PlayerObject_WalkAnimSpd)
				else
					if object.speed < -0x9FFFF
						object.animation = ANI_PEELOUT
					else
						object.animation = ANI_RUNNING
					end if
					CallFunction(PlayerObject_RunAnimSpd)
				end if
			end if
		end if
		if object.value14 > 0
			if temp7 == 1
				PlaySfx(SfxName[Skidding], 0)
			end if
			object.animation = ANI_SKIDDING
			object.animationSpeed = 0
			object.value14--
			if ringTimer == 0
				CreateTempObject(TypeName[Dust Puff], 0, object.xpos, object.ypos)
				object[tempObjectPos].iypos += object.collisionBottom
				object[tempObjectPos].drawOrder = player.sortedDrawOrder
			end if
			if object.speed > 0
				object.direction = FLIP_NONE
			else
				object.direction = FLIP_X
			end if
		end if
		if object.collisionMode == CMODE_FLOOR
			if object.pushing == 2
				object.animation = ANI_PUSHING
				object.animationSpeed = 0
			end if
		end if
		if object.jumpPress == 1
			CallFunction(PlayerObject_StartJump)
		else
			if object.up == 1
				if object.speed == 0
					if object.animation != ANI_FLAILING1
						if object.animation != ANI_FLAILING2
							object.state = PlayerObject_LookingUp
							object.value1 = 0
						else
							object.up = 0
							object.down = 0
						end if
					else
						object.up = 0
						object.down = 0
					end if
				end if
			end if
			if object.down == 1
				if object.speed == 0
					if object.animation != ANI_FLAILING1
						if object.animation != ANI_FLAILING2
							object.state = PlayerObject_Crouching
							object.value1 = 0
						else
							object.up = 0
							object.down = 0
						end if
					else
						object.up = 0
						object.down = 0
					end if
				else
					if object.left == 0
						if object.right == 0
							if object.speed > 0
								if object.speed > 0x8800
									object.state = PlayerObject_HandleRolling
									object.animation = ANI_JUMPING
									if object.prevAnimation != ANI_JUMPING
										object.iypos -= object.value30
									end if
									object.value2 = 0x400
									PlaySfx(SfxName[Rolling], 0)
								end if
							else
								if object.speed < -0x8800
									object.state = PlayerObject_HandleRolling
									object.animation = ANI_JUMPING
									if object.prevAnimation != ANI_JUMPING
										object.iypos -= object.value30
									end if
									object.value2 = 0x400
									PlaySfx(SfxName[Rolling], 0)
								end if
							end if
						end if
					end if
				end if
			end if
		end if
	end if
end function


function PlayerObject_HandleBored2
	if object.gravity == GRAVITY_AIR
		object.state = PlayerObject_HandleAir
		CallFunction(PlayerObject_HandleAirMovement)
	else
		CallFunction(PlayerObject_ResetOnFloor)
		if object.animation == ANI_CONTINUE_UP
			if object.frame == 1
				object.state = PlayerObject_HandleGround
			end if
		else
			object.animation = ANI_BORED
		end if
		if object.jumpPress == 1
			CallFunction(PlayerObject_StartJump)
		else
			if object.up == 1
				object.animation = ANI_CONTINUE_UP
			end if
			if object.down == 1
				object.animation = ANI_CONTINUE_UP
			end if
			if object.left == 1
				object.animation = ANI_CONTINUE_UP
			end if
			if object.right == 1
				object.animation = ANI_CONTINUE_UP
			end if
		end if
	end if
end function


function PlayerObject_HandleAir
	CallFunction(PlayerObject_AirAcceleration)
	if object.gravity == GRAVITY_AIR
		CallFunction(PlayerObject_HandleAirMovement)
		if object.yvel > 0x20000
			if object.animation == ANI_FLAILING1
				object.animation = ANI_WALKING
			end if
			if object.animation == ANI_FLAILING2
				object.animation = ANI_WALKING
			end if
		end if
		if object.animation == ANI_BOUNCING
			if object.yvel >= 0
				if object.value10 == ANI_STOPPED
					object.value10 = ANI_WALKING
				end if
				object.animation = object.value10
			end if
		end if
		if object.animation == ANI_SKIDDING
			if object.value14 > 0
				object.value14--
			else
				object.animation = ANI_WALKING
				object.prevAnimation = ANI_WALKING
				object.frame = 0
				object.animationSpeed = 40
			end if
		end if
		if object.animation == ANI_TWIRL
			if object.animationSpeed == 40
				if object.frame >= 12
					object.animation = ANI_WALKING
					object.prevAnimation = ANI_WALKING
					object.frame = 0
				end if
			else
				if object.frame >= 24
					object.animation = ANI_WALKING
					object.prevAnimation = ANI_WALKING
					object.frame = 0
					object.animationSpeed = 40
				end if
			end if
		end if
		if object.animation == ANI_HURT
			if object.yvel >= 0
				if object.value10 == ANI_STOPPED
					object.value10 = ANI_WALKING
				end if
				object.animation = object.value10
			end if
		end if
		if object.animation == ANI_JUMPING
			if object.value35 == 1
				if object.yvel >= object.value28
					CallFunction(object.value32)
				end if
			end if
		end if
	else
		object.state = PlayerObject_HandleGround
		CallFunction(PlayerObject_ResetOnFloor)
		object.value14 = 0
	end if
end function


function PlayerObject_Unknown
	CallFunction(PlayerObject_AirAcceleration)
	if object.gravity == GRAVITY_AIR
		CallFunction(PlayerObject_HandleAirMovement)
	else
		object.state = PlayerObject_HandleRollDecel
		CallFunction(PlayerObject_ResetOnFloor)
		object.value14 = 0
	end if
	object.animation = ANI_JUMPING
end function


function PlayerObject_HandleRolling
	CallFunction(PlayerObject_RollDecel2)
	if object.gravity == GRAVITY_AIR
		object.state = PlayerObject_HandleAir
		object.value1 = 0
		CallFunction(PlayerObject_HandleAirMovement)
	else
		CallFunction(PlayerObject_RollAnimSpd)
		object.animationSpeed = object.value5
		CallFunction(PlayerObject_ResetOnFloor)
		if object.jumpPress == 1
			CallFunction(PlayerObject_StartJump)
		end if
	end if
end function


function PlayerObject_RollingJump
	object.left = 0
	object.right = 0
	CallFunction(PlayerObject_AirAcceleration)
	if object.gravity == GRAVITY_AIR
		if object.animation == ANI_JUMPING
			if object.value35 == 1
				if object.yvel >= object.value28
					CallFunction(object.value32)
				end if
			end if
		end if
		CallFunction(PlayerObject_HandleAirMovement)
	else
		object.state = PlayerObject_HandleGround
		CallFunction(PlayerObject_ResetOnFloor)
		object.value14 = 0
	end if
end function


function PlayerObject_LookingUp
	if object.up == 0
		object.state = PlayerObject_HandleGround
		object.value1 = 0
	else
		if object.value1 < 60
			object.value1++
		else
			temp0 = object.ypos
			temp0 >>= 16
			temp0 -= screen.cameraY
			temp0 -= 112
			if object.lookPosY > temp0
				object.lookPosY -= 2
			end if
		end if
		object.animation = ANI_LOOKINGUP
		if object.gravity == GRAVITY_AIR
			object.state = PlayerObject_HandleAir
			object.value1 = 0
		else
			if object.jumpPress == 1
				CallFunction(PlayerObject_StartJump)
			end if
		end if
	end if
end function


function PlayerObject_Crouching
	if object.down == 0
		object.state = PlayerObject_HandleGround
		object.value1 = 0
	else
		if object.value1 < 60
			object.value1++
		else
			temp0 = object.ypos
			temp0 >>= 16
			temp0 -= screen.cameraY
			temp0 += 96
			if object.lookPosY < temp0
				object.lookPosY += 2
			end if
		end if
		object.animation = ANI_LOOKINGDOWN
		if object.gravity == GRAVITY_AIR
			object.state = PlayerObject_HandleAir
			object.value1 = 0
		else
			if object.jumpPress == 1
				CallFunction(object.value33)
			end if
		end if
	end if
end function


function PlayerObject_HandleSpindash
	if object.gravity == GRAVITY_AIR
		object.state = PlayerObject_HandleAir
		object.speed = 0
	end if
	if object.jumpPress == 1
		if object.value2 < 0x90000
			object.value2 += 0x20000
		else
			object.value2 = 0x80000
		end if
		object.frame = 0
		PlaySfx(SfxName[Charge], 0)
	else
		temp0 = object.value2
		temp0 >>= 5
		object.value2 -= temp0
	end if
	if object.down == 0
		object.value1 = 0
		object.state = PlayerObject_HandleRolling
		object.animation = ANI_JUMPING
		object.iypos -= object.value30
		if object.entityPos == screen.cameraTarget
			object.value11 = 15
			screen.cameraStyle = 4
		end if
		temp0 = object.value2
		temp0 >>= 17
		temp0 <<= 16
		if PlayerObject_SuperState == 1
			temp0 += 0xB0000
		else
			temp0 += 0x80000
		end if
		if object.direction == FLIP_NONE
			object.speed = temp0
		else
			object.speed = temp0
			FlipSign(object.speed)
		end if
		StopSfx(SfxName[Charge])
		PlaySfx(SfxName[Release], 0)
		CallFunction(PlayerObject_ResetOnFloor)
	end if
end function


function PlayerObject_StartFlyCarry
	if object.value36 != 0
		object.value36--
	end if
	temp0 = object.xpos
	temp1 = object.ypos
	temp1 += 0x1F0000
	if object[0].animation == ANI_JUMPING
		temp1 += 0x50000
	end if
	temp0 -= object[0].xpos
	temp1 -= object[0].ypos
	if object[0].state != PlayerObject_HandleFlyCarry
		CheckEqual(object[0].gravity, GRAVITY_GROUND)
		temp2 = checkResult
		CheckGreater(object.yvel, 0)
		temp2 &= checkResult
		if temp2 == 0
			CheckEqual(object[0].state, PlayerObject_HandleGround)
			temp2 = checkResult
			CheckEqual(object[0].state, PlayerObject_HandleRolling)
			temp2 |= checkResult
			CheckEqual(object[0].state, PlayerObject_HandleAir)
			temp2 |= checkResult
			CheckEqual(object[0].state, PlayerObject_RollingJump)
			temp2 |= checkResult
			CheckEqual(object[0].state, PlayerObject_LookingUp)
			temp2 |= checkResult
			CheckEqual(object[0].state, PlayerObject_Crouching)
			temp2 |= checkResult
			if temp2 != 0
				temp2 = temp0
				Abs(temp2)
				temp3 = temp1
				Abs(temp3)
				if temp2 <= 0x80000
					if temp3 <= 0x80000
						if object.value36 == 0
							if object[0].down == 0
								object[0].animation = ANI_HANGING
								object[0].state = PlayerObject_HandleFlyCarry
								object[0].xpos += temp0
								object[0].ypos += temp1
								PlaySfx(SfxName[Catch], 0)
							end if
						end if
					end if
				end if
			end if
		end if
	end if
	if object[0].state == PlayerObject_HandleFlyCarry
		temp2 = object.xpos
		temp3 = object.ypos
		temp6 = object.xvel
		temp7 = object.yvel
		ProcessObjectMovement()
		PlayerObject_SidekickX = object.xpos
		PlayerObject_SidekickY = object.ypos
		temp4 = object.xpos
		temp4 &= -0x10000
		temp5 = object.ypos
		temp5 &= -0x10000
		temp5 += 0x1F0000
		object.xpos = temp2
		object.ypos = temp3
		object.xvel = temp6
		object.yvel = temp7
		stage.entityPos = 0
		temp0 = object.xpos
		temp0 &= -0x10000
		temp1 = object.ypos
		temp1 &= -0x10000
		object.xvel = temp4
		object.yvel = temp5
		object.xvel -= temp0
		object.yvel -= temp1
		ProcessObjectMovement()
		stage.entityPos = 1
		object[0].collisionPlane = object.collisionPlane
		object[0].speed = object.speed
		object[0].direction = object.direction
		PlayerObject_LeaderX = object[0].xpos
		PlayerObject_LeaderY = object[0].ypos
		temp2 = object[0].xpos
		temp2 &= -0x10000
		temp3 = object[0].ypos
		temp3 &= -0x10000
		CheckNotEqual(temp4, temp2)
		temp6 = checkResult
		CheckNotEqual(temp5, temp3)
		temp6 |= checkResult
		if temp6 == 1
			if object[0].gravity == GRAVITY_GROUND
				object[0].state = PlayerObject_HandleGround
			else
				object[0].state = PlayerObject_HandleAir
			end if
			object.value36 = 30
		end if
	end if
end function


function PlayerObject_HandleFlyCarry
	if object[1].state != PlayerObject_HandleTailsFlight
		object.state = PlayerObject_HandleAir
	end if
	temp0 = object[1].xpos
	temp0 &= -0x10000
	temp2 = object.xpos
	temp2 &= -0x10000
	if object.xpos == PlayerObject_LeaderX
		PlayerObject_SidekickX &= -0x10000
		temp1 = temp0
		temp1 -= PlayerObject_SidekickX
		temp2 += temp1
	end if
	if temp0 != temp2
		if object.gravity == GRAVITY_GROUND
			object.state = PlayerObject_HandleGround
		else
			object.state = PlayerObject_HandleAir
		end if
	end if
	if object.gravity == GRAVITY_GROUND
		if object.yvel >= 0
			object.state = PlayerObject_HandleGround
		end if
	end if
	if object.jumpPress != 0
		if object.down != 0
			if object.value25 == 0x3800
				object.yvel = -0x40000
			else
				object.yvel = -0x20000
			end if
			object.state = PlayerObject_HandleAir
			object.animation = ANI_JUMPING
		end if
	end if
	if object.state == PlayerObject_HandleFlyCarry
		object.xvel = 0
		object.yvel = 0
		object.speed = 0
	else
		object[1].value36 = 30
	end if
end function


function PlayerObject_HandleTailsFlight
	CallFunction(PlayerObject_AirAcceleration)
	if object.gravity == GRAVITY_AIR
		object.xvel = object.speed
		if object.yvel < -0x10000
			object.value26 = 0x800
		else
			if object.yvel < 1
				if object.value2 < 60
					object.value2++
				else
					object.value26 = 0x800
				end if
			end if
		end if
		object.yvel += object.value26
		temp0 = stage.curYBoundary1
		temp0 += 16
		temp0 <<= 16
		if object.ypos < temp0
			if object.yvel < 0
				object.yvel = 0
			end if
		end if
		if options.vsMode == 0
			CallFunction(PlayerObject_StartFlyCarry)
		end if
		if object.value1 < 480
			if object.value25 == 0x3800
				if object[0].state == PlayerObject_HandleFlyCarry
					if object.yvel < 0
						object.animation = ANI_FLY_LIFT_UP
						object.animationSpeed = 240
					else
						object.animation = ANI_FLY_LIFT_DOWN
						object.animationSpeed = 120
					end if
				else
					object.animation = ANI_FLYING
					if object.yvel < 0
						object.animationSpeed = 240
					else
						object.animationSpeed = 120
					end if
				end if
			else
				if object[0].state == PlayerObject_HandleFlyCarry
					object.animation = ANI_SWIM_LIFT
				else
					object.animation = ANI_SWIMMING
					if object.yvel < 0
						object.animationSpeed = 60
					else
						object.animationSpeed = 30
					end if
				end if
			end if
			object.value1++
			if object.value1 == 480
				if object.value25 == 0x3800
					if object[0].state == PlayerObject_HandleFlyCarry
						object.animation = ANI_FLY_LIFT_TIRED
					else
						object.animation = ANI_FLYINGTIRED
					end if
					object.animationSpeed = 120
					StopSfx(SfxName[Flying])
					PlaySfx(SfxName[Tired], 1)
				else
					if object[0].state == PlayerObject_HandleFlyCarry
						object.animation = ANI_SWIM_LIFT
					else
						object.animation = ANI_SWIMMINGTIRED
					end if
				end if
			else
				if object.jumpPress == 1
					CheckNotEqual(object.value25, 0x3800)
					temp0 = checkResult
					CheckEqual(object[0].state, PlayerObject_HandleFlyCarry)
					temp0 &= checkResult
					if temp0 == 0
						object.value26 = -0x2000
						object.value2 = 0
					end if
				end if
			end if
		else
			if object.value25 == 0x3800
				if object[0].state == PlayerObject_HandleFlyCarry
					object.animation = ANI_FLY_LIFT_TIRED
				else
					object.animation = ANI_FLYINGTIRED
				end if
			else
				if object[0].state == PlayerObject_HandleFlyCarry
					object.animation = ANI_SWIM_LIFT
				else
					object.animation = ANI_SWIMMINGTIRED
				end if
			end if
		end if
	else
		object.animation = ANI_WALKING
		object.state = PlayerObject_HandleGround
		CallFunction(PlayerObject_ResetOnFloor)
	end if
end function


function PlayerObject_KnuxGlideLeft
	if object.gravity == GRAVITY_AIR
		if object.jumpHold == 1
			if object.value1 == 256
				if object.speed < 0x180000
					object.speed += 0x400
				end if
			else
				if object.speed < 0x40000
					object.speed += 0x1000
				end if
			end if
			if object.yvel > 0x8000
				object.yvel -= 0x2000
			else
				object.yvel += 0x2000
			end if
			if object.value1 < 256
				object.value1 += 4
			end if
			if object.value1 < 170
				if object.value1 > 86
					object.frame = 0
				else
					if object.value1 > 44
						object.frame = 1
					else
						object.frame = 2
					end if
				end if
			else
				if object.value1 < 212
					object.frame = 1
				else
					object.frame = 2
				end if
			end if
			temp7 = object.xpos
			if object.value1 < 128
				object.direction = FLIP_NONE
				temp0 = 0
				temp1 = 0
			else
				object.direction = FLIP_X
				object.xpos = temp7
				object.xpos += object.xvel
				object.ypos = object.ypos
				ObjectTileCollision(CSIDE_RWALL, -12, -2, object.collisionPlane)
				temp0 = checkResult
				temp2 = object.xpos
				object.xpos = temp7
				object.xpos += object.xvel
				ObjectTileCollision(CSIDE_RWALL, -12, 11, object.collisionPlane)
				temp1 = checkResult
				temp3 = object.xpos
			end if
			Cos(object.xvel, object.value1)
			object.xvel *= object.speed
			object.xvel >>= 9
			if object.right == 1
				object.state = PlayerObject_KnuxGlideRight
			end if
			object.xpos = temp7
			checkResult = temp0
			checkResult &= temp1
			if checkResult == 1
				if temp2 == temp3
					object.state = PlayerObject_KnuxWallClimb
					object.speed = 0
					object.xvel = 0
					object.yvel = 0
					object.value1 = 0
					PlaySfx(SfxName[Catch], 0)
				else
					object.value1 = 0
					object.xvel >>= 2
					object.speed = object.xvel
					object.animation = ANI_GLIDING_DROP
					object.state = PlayerObject_KnuxGlideDrop
				end if
			else
				if temp0 == 1
					object.value1 = 0
					object.xvel >>= 2
					object.speed = object.xvel
					object.animation = ANI_GLIDING_DROP
					object.state = PlayerObject_KnuxGlideDrop
				end if
			end if
		else
			object.value1 = 0
			object.xvel >>= 2
			object.speed = object.xvel
			object.animation = ANI_GLIDING_DROP
			object.state = PlayerObject_KnuxGlideDrop
		end if
	else
		if object.collisionMode == CMODE_FLOOR
			object.value1 = 0
			object.state = PlayerObject_KnuxGlideSlide
			object.animation = ANI_GLIDING_STOP
			object.speed = object.xvel
		else
			object.state = PlayerObject_HandleGround
			CallFunction(PlayerObject_ResetOnFloor)
			object.value14 = 0
		end if
	end if
	temp0 = stage.curYBoundary1
	temp0 += 16
	temp0 <<= 16
	if object.ypos < temp0
		object.xvel = 0
		object.speed = object.xvel
	end if
end function


function PlayerObject_KnuxGlideRight
	if object.gravity == GRAVITY_AIR
		if object.jumpHold == 1
			if object.value1 == 0
				if object.speed < 0x180000
					object.speed += 0x400
				end if
			else
				if object.speed < 0x40000
					object.speed += 0x1000
				end if
			end if
			if object.yvel > 0x8000
				object.yvel -= 0x2000
			else
				object.yvel += 0x2000
			end if
			if object.value1 > 0
				object.value1 -= 4
			end if
			if object.value1 < 170
				if object.value1 > 86
					object.frame = 0
				else
					if object.value1 > 44
						object.frame = 1
					else
						object.frame = 2
					end if
				end if
			else
				if object.value1 < 212
					object.frame = 1
				else
					object.frame = 2
				end if
			end if
			temp7 = object.xpos
			if object.value1 < 128
				object.direction = FLIP_NONE
				object.xpos = temp7
				object.xpos += object.xvel
				object.ypos = object.ypos
				ObjectTileCollision(CSIDE_LWALL, 12, -2, object.collisionPlane)
				temp0 = checkResult
				temp2 = object.xpos
				object.xpos = temp7
				object.xpos += object.xvel
				ObjectTileCollision(CSIDE_LWALL, 12, 11, object.collisionPlane)
				temp1 = checkResult
				temp3 = object.xpos
			else
				object.direction = FLIP_X
				temp0 = 0
				temp1 = 0
			end if
			Cos(object.xvel, object.value1)
			object.xvel *= object.speed
			object.xvel >>= 9
			if object.left == 1
				object.state = PlayerObject_KnuxGlideLeft
			end if
			object.xpos = temp7
			checkResult = temp0
			checkResult &= temp1
			if checkResult == 1
				temp2 >>= 1
				temp3 >>= 1
				if temp2 == temp3
					object.state = PlayerObject_KnuxWallClimb
					object.speed = 0
					object.xvel = 0
					object.yvel = 0
					object.value1 = 0
					PlaySfx(SfxName[Catch], 0)
				else
					object.value1 = 0
					object.xvel >>= 2
					object.speed = object.xvel
					object.animation = ANI_GLIDING_DROP
					object.state = PlayerObject_KnuxGlideDrop
				end if
			else
				if temp0 == 1
					object.speed = 0
					object.value1 = 0
					object.xvel >>= 2
					object.speed = object.xvel
					object.animation = ANI_GLIDING_DROP
					object.state = PlayerObject_KnuxGlideDrop
				end if
			end if
		else
			object.value1 = 0
			object.xvel >>= 2
			object.speed = object.xvel
			object.animation = ANI_GLIDING_DROP
			object.state = PlayerObject_KnuxGlideDrop
		end if
	else
		if object.collisionMode == CMODE_FLOOR
			object.value1 = 0
			object.state = PlayerObject_KnuxGlideSlide
			object.animation = ANI_GLIDING_STOP
			object.speed = object.xvel
		else
			object.state = PlayerObject_HandleGround
			CallFunction(PlayerObject_ResetOnFloor)
			object.value14 = 0
		end if
	end if
	temp0 = stage.curYBoundary1
	temp0 += 16
	temp0 <<= 16
	if object.ypos < temp0
		object.xvel = 0
		object.speed = object.xvel
	end if
end function


function PlayerObject_KnuxGlideDrop
	if object.gravity == GRAVITY_AIR
		CallFunction(PlayerObject_AirAcceleration)
		CallFunction(PlayerObject_HandleAirMovement)
	else
		if object.value1 == 0
			PlaySfx(SfxName[Landing], 0)
		end if
		object.scrollTracking = 0
		object.speed = 0
		object.xvel = 0
		object.animation = ANI_LOOKINGDOWN
		object.prevAnimation = ANI_LOOKINGDOWN
		object.frame = 2
		if object.value1 < 16
			object.value1++
		else
			object.state = PlayerObject_HandleGround
			CallFunction(PlayerObject_ResetOnFloor)
			object.value14 = 0
		end if
	end if
end function


function PlayerObject_KnuxGlideSlide
	if object.gravity == GRAVITY_GROUND
		if object.speed == 0
			object.scrollTracking = 0
			object.frame = 1
			if object.value1 < 16
				object.value1++
			else
				object.state = PlayerObject_HandleGround
				CallFunction(PlayerObject_ResetOnFloor)
				object.value14 = 0
			end if
		else
			if ringTimer == 0
				CreateTempObject(TypeName[Dust Puff], 0, object.xpos, object.ypos)
				object[tempObjectPos].iypos += object.collisionBottom
				object[tempObjectPos].drawOrder = player.sortedDrawOrder
				if object.value1 == 0
					PlaySfx(SfxName[Sliding], 0)
					object.value1 = 1
				else
					object.value1 = 0
				end if
			end if
			object.frame = 0
			if object.speed > 0
				object.speed -= 0x2000
				if object.speed < 0
					object.speed = 0
					object.value1 = 0
				end if
			else
				object.speed += 0x2000
				if object.speed > 0
					object.speed = 0
					object.value1 = 0
				end if
			end if
			if object.jumpHold == 0
				object.speed = 0
				object.value1 = 0
			end if
		end if
		object.xvel = object.speed
	else
		object.value1 = 0
		object.animation = ANI_GLIDING_DROP
		object.state = PlayerObject_KnuxGlideDrop
	end if
end function


function PlayerObject_KnuxWallClimb
	if object.gravity == GRAVITY_AIR
		object.animation = ANI_CLIMBING
		if object.up == 1
			if PlayerObject_SuperState == 1
				object.yvel = -0x20000
			else
				object.yvel = -0x10000
			end if
			temp0 = object.collisionTop
			temp0 *= -0x10000
			if object.ypos < temp0
				object.ypos = temp0
			end if
			object.value1++
			if object.value1 == 4
				object.value1 = 0
				object.frame++
				object.frame %= 6
			end if
		else
			if object.down == 1
				if PlayerObject_SuperState == 1
					object.yvel = 0x20000
				else
					object.yvel = 0x10000
				end if
				object.value1++
				if object.value1 == 4
					object.value1 = 0
					if object.frame < 1
						object.frame += 6
					end if
					object.frame--
				end if
			else
				object.yvel = 0
			end if
		end if
		if object.jumpPress == 1
			object.animation = ANI_JUMPING
			object.state = PlayerObject_HandleAir
			object.value1 = 0
			PlaySfx(SfxName[Jump], 0)
			if object.direction == FLIP_X
				object.xvel = 0x40000
				object.speed = 0x40000
				object.direction = FLIP_NONE
			else
				object.xvel = -0x40000
				object.speed = -0x40000
				object.direction = FLIP_X
			end if
			object.yvel = -0x40000
			if object.value25 != 0x3800
				object.xvel >>= 1
				object.speed >>= 1
				object.yvel >>= 1
			end if
		else
			if object.direction == FLIP_NONE
				temp2 = object.xpos
				ObjectTileGrip(CSIDE_LWALL, 10, -10, object.collisionPlane)
				temp0 = checkResult
				temp3 = object.xpos
				object.xpos = temp2
				ObjectTileGrip(CSIDE_LWALL, 10, 11, object.collisionPlane)
				temp1 = checkResult
				if object.xpos > temp3
					object.xpos = temp3
				end if
			else
				temp2 = object.xpos
				ObjectTileGrip(CSIDE_RWALL, -10, -10, object.collisionPlane)
				temp0 = checkResult
				temp3 = object.xpos
				object.xpos = temp2
				ObjectTileGrip(CSIDE_RWALL, -10, 11, object.collisionPlane)
				temp1 = checkResult
				if object.xpos < temp3
					object.xpos = temp3
				end if
			end if
			if temp0 == 0
				object.xpos = temp2
				object.animation = ANI_LEDGEPULLUP
				object.yvel = 0
				object.value1 = 0
				object.state = PlayerObject_KnuxLedgePullUp
				object.tileCollisions = 0
				if object.direction == FLIP_NONE
					object.xpos += 0x10000
				end if
			else
				if temp1 == 0
					object.animation = ANI_GLIDING_DROP
					object.prevAnimation = ANI_GLIDING_DROP
					object.frame = 2
					object.value1 = 0
					object.state = PlayerObject_KnuxGlideDrop
				end if
			end if
		end if
	else
		object.animation = ANI_WALKING
		object.state = PlayerObject_HandleGround
		CallFunction(PlayerObject_ResetOnFloor)
	end if
end function


function PlayerObject_KnuxLedgePullUp
	switch object.frame
	case 0
		if object.value1 < 5
			ObjectTileGrip(CSIDE_FLOOR, 12, -9, object.collisionPlane)
			object.value1++
		else
			object.value1 = 0
			object.frame++
			if object.direction == FLIP_NONE
				object.xpos += 0x90000
			else
				object.xpos -= 0x90000
			end if
			object.ypos -= 0xA0000
		end if
		break
	case 1
		if object.value1 < 5
			object.value1++
		else
			object.value1 = 0
			object.frame++
			if object.direction == FLIP_NONE
				object.xpos += 0x50000
			else
				object.xpos -= 0x50000
			end if
			object.ypos -= 0x20000
		end if
		break
	case 2
		if object.value1 < 5
			object.value1++
		else
			object.value1 = 0
			object.animation = ANI_STOPPED
			object.state = PlayerObject_HandleAir
			object.ypos -= 0xA0000
			object.tileCollisions = 1
		end if
		break
	end switch
end function


function PlayerObject_Hurt
	if object.value16 == 0
		arrayPos0 = object.entityPos
		arrayPos0 += playerCount
		if object.value37 != 0
			temp0 = 1
			ResetObjectEntity(arrayPos0, TypeName[Blank Object], 0, 0, 0)
			object.value37 = 0
			CheckEqual(options.spikeBehavior, 0)
			temp1 = checkResult
			CheckNotEqual(object.value8, 0)
			temp1 &= checkResult
			if temp1 == 1
				PlaySfx(SfxName[Spike], 0)
			else
				PlaySfx(SfxName[Hurt], 0)
			end if
		else
			if player.rings == 0
				if object.value8 != 0
					PlaySfx(SfxName[Spike], 0)
				else
					PlaySfx(SfxName[Hurt], 0)
				end if
				temp0 = 3
			else
				PlaySfx(SfxName[Lose Rings], 0)
				temp0 = 2
			end if
		end if
	else
		temp0 = 1
		if object.value8 != 0
			PlaySfx(SfxName[Spike], 0)
		else
			PlaySfx(SfxName[Hurt], 0)
		end if
	end if
	object.visible = 1
	switch temp0
	case 1
		object.state = PlayerObject_Knockback
		object.animation = ANI_HURT
		object.yvel = -0x40000
		object.gravity = GRAVITY_AIR
		object.scrollTracking = 1
		object.tileCollisions = 1
		object.value8 = 120
		if object.value25 == 0x1000
			object.speed >>= 1
			object.yvel >>= 1
		end if
		break
	case 2
		object.state = PlayerObject_Knockback
		object.animation = ANI_HURT
		object.yvel = -0x40000
		object.gravity = GRAVITY_AIR
		object.scrollTracking = 1
		object.tileCollisions = 1
		object.value8 = 120
		if object.value25 == 0x1000
			object.speed >>= 1
			object.yvel >>= 1
		end if
		temp0 = player.rings
		if temp0 > 16
			temp1 = temp0
			temp1 -= 16
			temp0 = 16
		else
			temp1 = 0
		end if
		if temp1 > 16
			temp1 = 16
		end if
		temp3 = temp1
		temp3 >>= 1
		temp3 <<= 5
		temp2 = 384
		temp2 -= temp3
		temp3 >>= 4
		if temp3 == temp1
			temp2 += 16
		else
			temp2 -= 16
		end if
		temp3 = 0
		while temp3 < temp1
			CreateTempObject(TypeName[Lose Ring], object.collisionPlane, object.xpos, object.ypos)
			Cos(object[tempObjectPos].xvel, temp2)
			Sin(object[tempObjectPos].yvel, temp2)
			object[tempObjectPos].xvel <<= 8
			object[tempObjectPos].yvel <<= 8
			object[tempObjectPos].animationSpeed = 256
			object[tempObjectPos].inkEffect = INK_ALPHA
			object[tempObjectPos].alpha = 256
			temp3++
			temp2 += 32
		loop
		temp3 = temp0
		temp3 >>= 1
		temp3 <<= 5
		temp2 = 384
		temp2 -= temp3
		temp3 >>= 4
		if temp3 == temp0
			temp2 += 16
		else
			temp2 -= 16
		end if
		temp3 = 0
		while temp3 < temp0
			CreateTempObject(TypeName[Lose Ring], object.collisionPlane, object.xpos, object.ypos)
			Cos(object[tempObjectPos].xvel, temp2)
			Sin(object[tempObjectPos].yvel, temp2)
			object[tempObjectPos].xvel <<= 9
			object[tempObjectPos].yvel <<= 9
			object[tempObjectPos].animationSpeed = 256
			object[tempObjectPos].inkEffect = INK_ALPHA
			object[tempObjectPos].alpha = 256
			temp3++
			temp2 += 32
		loop
		player.rings 	= 0
		ringExtraLife 	= 100
		break
	case 3
		player.sortedDrawOrder = 6
		object.speed = 0
		object.yvel = -0x70000
		object.xvel = 0
		object.state = PlayerObject_Death
		object.animation = ANI_DYING
		object.tileCollisions = 0
		object.interaction = 0
		if object.entityPos == screen.cameraTarget
			object.priority = PRIORITY_ACTIVE_PAUSED
			if object[1].type == TypeName[Player 2 Object]
				object[1].priority = PRIORITY_ACTIVE_PAUSED
			end if
			screen.cameraEnabled = 0
			if options.vsMode == 0
				stage.state = 3
			end if
		end if
		if object[+playerCount].type == invincibilityType
			object[+playerCount].propertyValue = 3
		end if
		object[+playerCount].type = TypeName[Blank Object]
		break
	end switch
end function


function PlayerObject_Knockback
	if object.gravity == GRAVITY_AIR
		object.scrollTracking = 1
		if object.value25 == 0x3800
			object.yvel += 0x3000
		else
			object.yvel += 0xF00
		end if
		object.xvel = object.speed
	else
		object.state = PlayerObject_HandleGround
		object.speed = 0
		object.xvel = 0
		CallFunction(PlayerObject_ResetOnFloor)
	end if
end function


function PlayerObject_Death
	if object.entityPos == 0
		if PlayerObject_SuperState == 1
			PlayerObject_SuperState = 2
		end if
	end if
	if object.controlMode != -1
		object.yvel = -0x70000
		object.controlMode = -1
	end if
	if object.value8 != 0
		object.value8 = 0
		object.visible = 1
	end if
	object.yvel += 0x3800
	if object.animation != ANI_BORED
		object.animation = ANI_DYING
	end if
	if object.entityPos == screen.cameraTarget
		temp0 = screen.cameraY
		temp0 += 272
		temp0 <<= 16
		if object.ypos > temp0
			object.ypos = temp0
		end if
	end if
	if object.yvel > 0x100000
		if object.value16 == 0
			arrayPos0 = 25
			arrayPos0 += object.entityPos
			if player.lives > 0
				if options.bossGame != 1
					player.lives--
				endif
			endif
			if options.vsMode == 0
				stage.timeEnabled = 0
				object.type = TypeName[Death Event]
				deathEvent.drawOrder = 6
				deathEvent.leftTextPos = screen.xcenter
				deathEvent.leftTextPos -= 264
				deathEvent.rightTextPos = screen.xcenter
				deathEvent.rightTextPos += 200
				if options.gameMode == 2
					deathEvent.timer = 0
					deathEvent.state = 3
				else
					if player.lives == 0
						deathEvent.timer = -0xB40
						deathEvent.state = 0
						PlayMusic(5)
						stage.pauseEnabled = 0
					else
						deathEvent.timer = 0
						deathEvent.state = 2
						if stage.timeOver == 1
							deathEvent.timer = -0xB40
							deathEvent.state = 1
							PlayMusic(5)
							stage.pauseEnabled = 0
						end if
					end if
				end if
			else
				if player.lives == 0
					player.type = TypeName[Death Event]
					deathEvent.state = 0
				end if
				if stage.timeOver == 1
					player.type = TypeName[Death Event]
					deathEvent.state = 1
				end if
				if object.type == TypeName[Death Event]
					deathEvent.drawOrder = 6
					deathEvent.leftTextPos = screen.xcenter
					deathEvent.leftTextPos -= 264
					deathEvent.rightTextPos = screen.xcenter
					deathEvent.rightTextPos += 200
					deathEvent.timer = -0xB40
					PlayMusic(5)
					stage.pauseEnabled = 0
				else
					object.state = PlayerObject_HandleAir
					player.rings = 0
					object.priority = PRIORITY_ACTIVE
					object.gravity = GRAVITY_AIR
					object.animation = ANI_HURT
					if object.entityPos == 0
						object.xpos = vs.restartX1
						object.ypos = vs.restartY1
					else
						object.xpos = vs.restartX2
						object.ypos = vs.restartY2
					end if
					object.direction = FLIP_NONE
					object.tileCollisions = 1
					object.interaction = 1
					object.visible = 1
					object.controlMode = 0
					object.scrollTracking = 1
					object.drawOrder = DRAWORDER_PLAYER
					player.sortedDrawOrder = 4
					object.collisionPlane = PATH_A
					if object.entityPos == screen.cameraTarget
						CreateTempObject(TypeName[VS Game], 0, object.xpos, object.ypos)
						object[tempObjectPos].value0 = 384
						object[tempObjectPos].state = 2
						screen.cameraX = object.ixpos
						screen.cameraY = object.iypos
						screen.cameraEnabled = 1
					end if
				end if
			end if
		end if
	end if
end function


function PlayerObject_Drown
	if object.entityPos == 0
		if PlayerObject_SuperState == 1
			PlayerObject_SuperState = 2
		end if
	end if
	object.controlMode = -1
	object.yvel += object.value25
	object.animation = ANI_DROWNING
	if object.entityPos == screen.cameraTarget
		temp0 = screen.cameraY
		temp0 += 272
		temp0 <<= 16
		if object.ypos > temp0
			object.ypos = temp0
		end if
	end if
	if object.yvel > 0x80000
		if object.value16 == 0
			arrayPos0 = 25
			arrayPos0 += object.entityPos
			if player.lives > 0
				if options.bossGame != 1
					player.lives--
				endif
			endif
			if options.vsMode == 0
				stage.timeEnabled = 0
				object.type = TypeName[Death Event]
				deathEvent.drawOrder = 6
				deathEvent.leftTextPos = screen.xcenter
				deathEvent.leftTextPos -= 264
				deathEvent.rightTextPos = screen.xcenter
				deathEvent.rightTextPos += 200
				if options.gameMode == 2
					deathEvent.timer = 0
					deathEvent.state = 3
				else
					if player.lives == 0
						deathEvent.timer = -0xB40
						deathEvent.state = 0
						PlayMusic(5)
						stage.pauseEnabled = 0
					else
						deathEvent.timer = 0
						deathEvent.state = 2
					end if
				end if
			else
				object.state = PlayerObject_HandleAir
				player.rings = 0
				object.priority = PRIORITY_ACTIVE
				object.gravity = GRAVITY_AIR
				object.animation = ANI_HURT
				if object.entityPos == 0
					object.xpos = vs.restartX1
					object.ypos = vs.restartY1
				else
					object.xpos = vs.restartX2
					object.ypos = vs.restartY2
				end if
				object.direction = FLIP_NONE
				object.tileCollisions = 1
				object.interaction = 1
				object.visible = 1
				object.controlMode = 0
				object.scrollTracking = 1
				object.drawOrder = DRAWORDER_PLAYER
				player.sortedDrawOrder = 4
				object.collisionPlane = PATH_A
				if object.entityPos == screen.cameraTarget
					CreateTempObject(TypeName[VS Game], 0, object.xpos, object.ypos)
					object[tempObjectPos].value0 = 384
					object[tempObjectPos].state = 2
					screen.cameraX = object.ixpos
					screen.cameraY = object.iypos
					screen.cameraEnabled = 1
				end if
			end if
		end if
	end if
end function


function PlayerObject_CheckTile
	if object.left == 1
		object.direction = FLIP_X
		object.speed = -0x20000
		object.animationSpeed = 30
	else
		if object.right == 1
			object.direction = FLIP_NONE
			object.speed = 0x20000
			object.animationSpeed = 30
		else
			object.speed = 0
			object.animationSpeed = 0
		end if
	end if
	temp1 = object.xpos
	temp1 >>= 16
	temp2 = object.ypos
	temp2 >>= 16
	temp2 += object.collisionTop
	Get16x16TileInfo(temp0, temp1, temp2, TILEINFO_ANGLEB)
	if temp0 != 3
		object.state = PlayerObject_HandleAir
		object.speed = 0
		object.animationSpeed = 0
		object.yvel = 0
	end if
	if object.jumpPress == 1
		object.state = PlayerObject_HandleAir
		object.yvel = 0
		object.speed = 0
		object.animationSpeed = 0
		object.ypos += 0x40000
	end if
	object.xvel = object.speed
end function


function PlayerObject_HandleRollDecel
	if object.gravity == GRAVITY_AIR
		object.state = PlayerObject_Unknown
		object.value1 = 0
		CallFunction(PlayerObject_HandleAirMovement)
	else
		if object.speed > 0
			if object.collisionMode == CMODE_FLOOR
				if object.speed < 0x10000
					object.speed = 0x40000
				end if
			end if
		else
			if object.collisionMode == CMODE_FLOOR
				if object.speed > -0x10000
					object.speed = -0x40000
				end if
			end if
		end if
		if object.right == 1
			if object.speed < 0
				object.speed += object.value31
			end if
		end if
		if object.left == 1
			if object.speed > 0
				object.speed -= object.value31
			end if
		end if
		if object.speed > 0
			object.speed -= object.value29
			Sin256(temp0, object.angle)
			if temp0 > 0
				Sin256(temp0, object.angle)
				temp0 *= 0x5000
			else
				Sin256(temp0, object.angle)
				temp0 *= 0x1E00
			end if
			temp0 >>= 8
			object.speed += temp0
		else
			object.speed += object.value29
			Sin256(temp0, object.angle)
			if temp0 < 0
				Sin256(temp0, object.angle)
				temp0 *= 0x5000
			else
				Sin256(temp0, object.angle)
				temp0 *= 0x1E00
			end if
			temp0 >>= 8
			object.speed += temp0
		end if
		CallFunction(PlayerObject_RollAnimSpd)
		object.animationSpeed = object.value5
		CallFunction(PlayerObject_ResetOnFloor)
	end if
end function


function PlayerObject_Clinging
	object.gravity = GRAVITY_AIR
	if object.animation != ANI_CLINGING
		object.xvel = 0x80000
		object.speed = 0x80000
	else
		object.xvel = 0
		object.speed = 0
	end if
	if object.up == 1
		object.ypos -= 0x10000
	else
		if object.down == 1
			object.ypos += 0x10000
		end if
	end if
	object.yvel = 0
end function


function PlayerObject_Waterslide
	if object.gravity == GRAVITY_AIR
		object.state = PlayerObject_HandleAir
		object.angle = 0
		object.collisionMode = CMODE_FLOOR
		object.value1 = 0
		CallFunction(PlayerObject_HandleAirMovement)
		object.animation = ANI_WATERSLIDE
	else
		if object.direction == FLIP_NONE
			object.speed = 0xA0000
		else
			object.speed = -0xA0000
		end if
		CallFunction(PlayerObject_RollAnimSpd)
		object.animation = ANI_WATERSLIDE
		CallFunction(PlayerObject_ResetOnFloor)
		if object.jumpPress == 1
			CallFunction(PlayerObject_StartJump)
		end if
	end if
end function


function PlayerObject_HandleContRun
	if object.speed > 0x10000
		object.value1 = 0
		if object.speed < 0x5F5C2
			object.animation = ANI_WALKING
			CallFunction(PlayerObject_WalkAnimSpd)
		else
			if object.speed > 0x9FFFF
				object.animation = ANI_PEELOUT
			else
				object.animation = ANI_RUNNING
			end if
			CallFunction(PlayerObject_RunAnimSpd)
		end if
	end if
end function


event ObjectMain
	if stage.debugMode == 1
		CallFunction(PlayerObject_ProcessPlayer)
		CheckEqual(options.attractMode, 0)
		temp0 = checkResult
		CheckEqual(inputPress.buttonB, 1)
		temp0 &= checkResult
		if temp0 == 1
			object.type = TypeName[Debug Mode]
			object.yvel = 0
			object.state = PlayerObject_Blank
			object.frame = 0
			object.rotation = 0
			object.interaction = 0
			object.drawOrder = 4
			object.priority = PRIORITY_ACTIVE
			object.value8 = 0
			object.visible = 1
			object.value2 = 0
			object.value3 = 0
			object.value4 = 0
			object.frame = object.value17
			screen.cameraEnabled = 1
			screen.cameraStyle = 0
			player.hitboxLeft 	= HITBOX_AUTO
			player.hitboxTop 	= HITBOX_AUTO
			player.hitboxRight 	= HITBOX_AUTO
			player.hitboxBottom = HITBOX_AUTO
			if stage.state == 3
				stage.state = STAGE_RUNNING
			end if
			if object[1].type == TypeName[Player 2 Object]
				object[1].priority = PRIORITY_ACTIVE
			end if
			if object[+playerCount].propertyValue == 3
				object[+playerCount].type = invincibilityType
				object[+playerCount].propertyValue = 0
			end if
		else
			if object.gravity == GRAVITY_GROUND
				object.value35 = 0
			end if
			CallFunction(object.state)
			ProcessAnimation()
			if object.entityPos == screen.cameraTarget
				if object.animation == ANI_JUMPING
					screen.adjustCameraY = object.value30
				else
					if screen.adjustCameraY == object.value30
						screen.adjustCameraY = 0
						object.iypos += object.value30
					end if
				end if
			end if
			if object.value34 == 0
				temp0 = player.prevGravity
				player.prevGravity = object.gravity
				ProcessObjectMovement()
				player.prevGravity ^= 1
				CheckEqual(object.gravity, GRAVITY_GROUND)
				player.prevGravity |= checkResult
				player.prevGravity ^= 1
				if temp0 == 1
					if player.prevGravity == 0
						object.value19 = 0
						if object.animation == ANI_JUMPING
							if object.down == 0
								if object.state != PlayerObject_BubbleBounce
									if object.state != PlayerObject_HandleRolling
										if object.state != PlayerObject_HandleRollDecel
											object.animation = ANI_WALKING
											if object.entityPos == screen.cameraTarget
												screen.adjustCameraY = 0
											end if
											object.iypos += object.value30
										end if
									end if
								end if
							end if
						end if
					end if
				end if
			else
				object.value34 = 0
			end if
		end if
	else
		CallFunction(PlayerObject_ProcessPlayer)
		if object.gravity == GRAVITY_GROUND
			object.value35 = 0
		end if
		CallFunction(object.state)
		ProcessAnimation()
		if object.entityPos == screen.cameraTarget
			if object.animation == ANI_JUMPING
				screen.adjustCameraY = object.value30
			else
				if screen.adjustCameraY == object.value30
					screen.adjustCameraY = 0
					object.iypos += object.value30
				end if
			end if
		end if
		if object.value34 == 0
			temp0 = player.prevGravity
			player.prevGravity = object.gravity
			ProcessObjectMovement()
			player.prevGravity ^= 1
			CheckEqual(object.gravity, GRAVITY_GROUND)
			player.prevGravity |= checkResult
			player.prevGravity ^= 1
			if temp0 == 1
				if player.prevGravity == 0
					object.value19 = 0
					if object.animation == ANI_JUMPING
						if object.down == 0
							if object.state != PlayerObject_BubbleBounce
								if object.state != PlayerObject_HandleRolling
									if object.state != PlayerObject_HandleRollDecel
										object.animation = ANI_WALKING
										if object.entityPos == screen.cameraTarget
											screen.adjustCameraY = 0
										end if
										object.iypos += object.value30
									end if
								end if
							end if
						end if
					end if
				end if
			end if
		else
			object.value34 = 0
		end if
	end if
	CallFunction(PlayerObject_ProcessSuperState)
end event


event ObjectDraw
	if object.animation != object.prevAnimation
		object.prevAnimation = object.animation
		object.frame = 0
		object.animationTimer = 0
		object.animationSpeed = 0
	end if
	DrawObjectAnimation()
end event


event ObjectStartup
	playerCount = 0
	foreach (TypeName[Player Object], arrayPos0, ALL_ENTITIES)
		screen.cameraEnabled = 1
		screen.cameraStyle = 0
		screen.cameraTarget = 0
		currentPlayer = 0
		if stage.playerListPos > 2
			stage.playerListPos = 0
			stage.player2Enabled = 1
		end if
		ResetObjectEntity(0, TypeName[Player Object], 0, object[arrayPos0].xpos, object[arrayPos0].ypos)
		screen.cameraX = player[0].ixpos
		screen.cameraY = player[0].iypos
		object[0].groupID = GROUP_PLAYERS
		object[0].state = PlayerObject_HandleAir
		object[0].priority = PRIORITY_ACTIVE
		object[0].drawOrder = DRAWORDER_PLAYER
		player[0].sortedDrawOrder = 4
		object[0].value31 = 0x2000
		object[0].value33 = PlayerObject_StartSpindash
		player[0].hitboxLeft 	= HITBOX_AUTO
		player[0].hitboxTop 	= HITBOX_AUTO
		player[0].hitboxRight 	= HITBOX_AUTO
		player[0].hitboxBottom 	= HITBOX_AUTO
		PlayerObject_SuperState = 0
		PlayerObject_value1 = 0
		PlayerObject_value2 = 0
		PlayerObject_value3 = 0
		switch stage.playerListPos
		case 0
			LoadAnimation("SuperSonic.ani")
			LoadAnimation("Sonic.ani")
			CallFunction(PlayerObject_ProcessSuperPalS)
			object[0].propertyValue = 0
			object[0].value30 = -5
			object[0].value32 = PlayerObject_ShieldAbilities
			ANI_PEELOUT = ANI_RUNNING
			break
		case 1
			object[0].type = TypeName[Tails Object]
			object[0].propertyValue = 1
			CallFunction(PlayerObject_ProcessSuperPalT)
			LoadAnimation("Tails.ani")
			object[0].value30 = -1
			if options.vsMode == 1
				options.tailsFlight = 1
			end if
			if options.tailsFlight == 1
				object[0].value32 = PlayerObject_StartTailsFlight
			else
				object[0].value32 = PlayerObject_Blank
			end if
			stage.player2Enabled = 0
			break
		case 2
			LoadAnimation("Knuckles.ani")
			CallFunction(PlayerObject_ProcessSuperPalK)
			object[0].propertyValue = 2
			object[0].value30 = -5
			object[0].value32 = PlayerObject_StartKnuxGlide
			ANI_PEELOUT = ANI_RUNNING
			if options.saveSlot > 0
				stage.player2Enabled = 0
			end if
			break
		end switch
		if stage.player2Enabled == 1
			playerCount = 2
		else
			playerCount = 1
		end if
		currentPlayer = 0
		CallFunction(PlayerObject_SwitchPhysicsState)
		ResetObjectEntity(arrayPos0, TypeName[Blank Object], 0, 0, 0)
	next
end event

event RSDKDraw
	DrawSprite(0)
end event

event RSDKLoad
	LoadSpriteSheet("Global/Display.gif")
	SpriteFrame(-16, -16, 32, 32, 1, 143)
end event